无法获得正确的XSLT输出

时间:2012-02-24 03:59:41

标签: xslt xslt-2.0 xpath-2.0

我有这样的XML:

<?xml version="1.0" encoding="UTF-8"?>
<Section>
    <Chapter>
        <nametable>
            <namerow>
                <namecell stuff="1">
                    <entity>A</entity>
                </namecell>
                <namecell stuff="2">
                    <entity>B</entity>
                </namecell>
            </namerow>
        </nametable>
    </Chapter>
</Section>

我的XSLT是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

<xsl:output method="text"/>

    <xsl:template match="/">
        <xsl:apply-templates select="Section/Chapter//nametable"/>
    </xsl:template>

    <xsl:template match="nametable">
        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>
    </xsl:template>

<xsl:template match="text()"/>

</xsl:stylesheet>

奇怪的是我按照这个顺序得到一个输出1 2 A B,我以为我会得到1 A 2 B。

不确定为什么会这样?。

TIA,

约翰

3 个答案:

答案 0 :(得分:3)

您的问题在这里

        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>

与XSLT 2.0中的XSLT 1.0不同,xsl:value-of指令输出select属性中指定序列的所有项。

这意味着

<xsl:value-of select="./namecell/@stuff"/>

输出所有stuff属性(1和2)

然后是下一条指令:

           <xsl:value-of select="./namecell" />

输出两个namecell子项的字符串值 - 分别为"A""B"

<强>解决方案

<强>替换

        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>

<强>与

        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/(@stuff|entity)"/>
        </xsl:for-each>

此修改的完整代码

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        version="2.0">

    <xsl:output method="text"/>

        <xsl:template match="/">
            <xsl:apply-templates select="Section/Chapter//nametable"/>
        </xsl:template>

        <xsl:template match="nametable">
            <xsl:for-each select="./namerow">
                <xsl:value-of select="./namecell/(@stuff|entity)"/>
            </xsl:for-each>
        </xsl:template>

    <xsl:template match="text()"/>
</xsl:stylesheet>

并且在提供的XML文档上应用此转换时

<Section>
    <Chapter>
        <nametable>
            <namerow>
                <namecell stuff="1">
                    <entity>A</entity>
                </namecell>
                <namecell stuff="2">
                    <entity>B</entity>
                </namecell>
            </namerow>
        </nametable>
    </Chapter>
</Section>

生成了想要的结果

1 A 2 B

第二种解决方案(可能是您最初打算做的):

<强>替换

    <xsl:template match="nametable">
        <xsl:for-each select="./namerow">
            <xsl:value-of select="./namecell/@stuff"/>
            <xsl:value-of select="./namecell" />
        </xsl:for-each>
    </xsl:template>

<强>与

    <xsl:template match="nametable">
        <xsl:for-each select="namerow/namecell">
            <xsl:value-of select="@stuff"/>
            <xsl:value-of select="entity"/>
        </xsl:for-each>
    </xsl:template>

现在再次获得想要的结果

1A2B

答案 1 :(得分:1)

我正在使用msxml,我将1 A作为op:|

这里有一个解决方案,它像gem一样工作:)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="2.0">

  <xsl:output method="text"/>

  <xsl:template match="/Section/Chapter/nametable/namerow/namecell">
    <xsl:value-of select="@stuff"/>
    <xsl:text> </xsl:text><!--inserting a space-->
    <xsl:value-of select="entity"/>
    <xsl:text> </xsl:text><!--inserting a space-->
  </xsl:template>
  <xsl:template match="text()"/>

</xsl:stylesheet>

答案 2 :(得分:1)

您看到的行为的原因是您在namerow上进行迭代。如果您将在namecell上迭代为<xsl:for-each select="namerow/namecell"><xsl:value-of select="@stuff"/><xsl:value-of select="." /></xsl:for-each>,您将获得1A2B。您将要记住每个XPath(例如@stuff)不一定给您一个值(一个节点),而是一组值(一个节点集)。该集通常恰好只包含一个值,但不要被愚弄。

同一事物的另一种语法:<xsl:for-each select="namerow"><xsl:for-each select="namecell"><xsl:value-of select="@stuff"/><xsl:value-of select="." /></xsl:for-each></xsl:for-each>

P.S。就像在文件系统路径中一样,你不必写&#34; ./"在XPath之前。