为什么xslt产生不希望的结果

时间:2013-02-16 15:08:07

标签: xml 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>

我的问题是,为什么我会在Hope元素之后获得额外的asdf文本?

2 个答案:

答案 0 :(得分:2)

由于Test元素与<xsl:template match="soapenv:Body//*">匹配,后者在输出中创建了Test元素,因此将模板应用于其子元素(复制Hope元素)和然后附加一个包含Test元素本身的字符串值的文本节点 - 这是其所有后代文本节点的串联,包括Hope内的一个。

你可以通过在有问题的元素没有元素子元素的情况下使<xsl:value-of>仅触发来解决此问题,方法是将其包装在

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

或使用soapenv:Body//*[*]

的单独模板

答案 1 :(得分:2)

您似乎想要摆脱命名空间。 (为什么?实际上这不应该是必要的!

考虑一种更惯用的方法。

<!-- 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>