为什么XSLT产生意想不到的结果

问题描述:

我的XSLT:为什么XSLT产生意想不到的结果

<xsl:template match="node()"> 
    <xsl:apply-templates /> 
</xsl:template> 

<xsl:template match="soapenv:Body//*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="@* | *" /> 
     <xsl:value-of select="." /> 
    </xsl:element> 
</xsl:template> 

<xsl:template match="soapenv:Body//@*"> 
    <xsl:attribute name="{local-name()}"> 
     <xsl:value-of select="." /> 
    </xsl:attribute> 
</xsl:template> 

输入:

<soapenv:Body> 
    <Test asdf="asdfasdf"> 
     <Hope>asdf</Hope> 
    </Test> 
</soapenv:Body> 

输出:

<Test asdf="asdfasdf"> 
    <Hope>asdf</Hope> 
    asdf 
</Test> 

我的问题是,为什么我收到后,多余的ASDF文本希望元素?

因为你Test元素由<xsl:template match="soapenv:Body//*">,这在输出创建Test元素匹配,应用模板到其子(复制Hope元素),然后追加包含Test元素本身的字符串值的文本节点 - 这是所有后代文本节点的连接,包括Hope中的一个。

你可以通过使当有问题的元件不具有子元素的<xsl:value-of>只火,无论是在

<xsl:if test="not(*)"> 

包裹,或通过使用一个单独的模板soapenv:Body//*[*]

您解决这个问题似乎想要摆脱名称空间。 (为什么?这实际上不是必须的!

考虑一个更习惯的方法。

<!-- 1) always try to start off with the identity template --> 
<xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node() | @*" /> 
    </xsl:copy> 
</xsl:template> 

<!-- 2) only create templates for nodes that need extra processing --> 
<xsl:template match="soapenv:*"> 
    <xsl:element name="{local-name()}"> 
     <xsl:apply-templates select="node() | @*" /> 
    </xsl:element> 
</xsl:template> 

结果与你输入:

<Body> 
    <Test asdf="asdfasdf"> 
     <Hope>asdf</Hope> 
    </Test> 
</Body> 

编辑:如果你只是想在开始正文内容输出,使用:

<xsl:template match="/"> 
    <xsl:apply-templates select="soapenv:Envelope/soapenv:Body/*" /> 
</xsl:template>