问题
I have a XML like this:
<?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>
My XSLT is like this:
<?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>
Odd is I'm getting an output in this order 1 2 A B, I thought I'm going to get 1 A 2 B.
Not sure why is that ?.
TIA,
John
回答1:
Your problem is here:
<xsl:for-each select="./namerow">
<xsl:value-of select="./namecell/@stuff"/>
<xsl:value-of select="./namecell" />
</xsl:for-each>
Unlike in XSLT 1.0 in XSLT 2.0 the xsl:value-of
instruction outputs all items of the sequence specified in its select
attribute.
This means that
<xsl:value-of select="./namecell/@stuff"/>
outputs all stuff
attributes (1 and 2)
then the next instruction:
<xsl:value-of select="./namecell" />
outputs the string value of the two namecell
children -- respectively "A"
and "B"
.
Solution:
Replace:
<xsl:for-each select="./namerow">
<xsl:value-of select="./namecell/@stuff"/>
<xsl:value-of select="./namecell" />
</xsl:for-each>
with:
<xsl:for-each select="./namerow">
<xsl:value-of select="./namecell/(@stuff|entity)"/>
</xsl:for-each>
The complete code with this modification is:
<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>
and when this transformation is applied on the provided XML document:
<Section>
<Chapter>
<nametable>
<namerow>
<namecell stuff="1">
<entity>A</entity>
</namecell>
<namecell stuff="2">
<entity>B</entity>
</namecell>
</namerow>
</nametable>
</Chapter>
</Section>
the wanted result is produced:
1 A 2 B
Second solution (probably what you intended to do in the first place):
Replace:
<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>
with:
<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>
Now you again get the wanted result:
1A2B
回答2:
I am using msxml, am getting 1 A
as op :|
Well here is a solution for you it works like 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>
回答3:
The reason for the behavior you see is that you iterate over namerow. You will get 1A2B if you will instead iterate over namecell as: <xsl:for-each select="namerow/namecell"><xsl:value-of select="@stuff"/><xsl:value-of select="." /></xsl:for-each>
. You'll want to remember that each XPath such as @stuff
gives you not necessarily one value (a node), but rather a set of values (a nodeset). That set will commonly happen to contain only one value, but don't be fooled.
Another syntax for the same thing: <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. Just as in a filesystem path, you don't have to write "./" before an XPath.
来源:https://stackoverflow.com/questions/9425190/cant-get-correct-xslt-output