2012-02-24 98 views
2

我有这样的XML:无法获得正确的XSLT输出

<?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 AB,我以为我会得到1 A 2 B.

不知道为什么?

TIA,

约翰

回答

3

你的问题是在这里

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

不像在XSLT 1.0 XSLT 2.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 
+0

哦!这里是答案:) +1 – 2012-02-24 04:44:32

+0

Dimitri:这是什么真的吗? – JohnX 2012-02-24 04:48:53

+0

@JohnX:''作为文本节点输出每个'namecell'的每个'stuff'属性和'entity'子元素的字符串值当前节点的子节点。在这里我使用Xpath * union *运算符'|'。在位置步骤中的这种联合只能在XPath 2.0中使用 - 在XPath 1.0中语法上是非法的。 – 2012-02-24 05:04:31

1

我使用MSXML,我越来越1 A为OP:|

那么这里是为你解决它像宝石:)

<?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> 
+0

这就是我所做的,以获得CORRE ct答案,我正在使用Saxon EE,但我不明白为什么我原来的帖子不能像它应该的那样工作。 – JohnX 2012-02-24 04:21:33

+0

这可能是因为你正在使用'/ namecell/@ stuff'而不是'/ @ stuff' ..我没有真正专注于xslt 2.0所以不太确定.. – 2012-02-24 04:43:33

+0

请参阅Dimitre的答案.. – 2012-02-24 04:46:48

1

的理由让你看到的行为是你遍历namerow。您将获得1A2B,如果您将代替名称单元重复:<xsl:for-each select="namerow/namecell"><xsl:value-of select="@stuff"/><xsl:value-of select="." /></xsl:for-each>。您需要记住每个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>

附:就像在文件系统路径中一样,您不必在XPath之前编写“./”。

+0

合理。谢谢! – JohnX 2012-02-24 04:50:07