我有这样的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,
约翰
答案 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之前。