I have an xml file that looks like this:
<args>
<sometag value="abc" />
<anothertag value="def" />
<atag value="blah" />
</args>
keep in mind that tag names within args could be named anything (I don't know ahead of time) Now i have this xml file stored in a variable called $data which I loaded using a document() call in the xslt stylesheet (its not the backing data for the xslt file)
I want to take that data and produce the followin开发者_如何学Pythong output: sometag=abc&anothertag=def&atag=blah
so (a very simplified verison looks like this:
<xsl:template>
<xsl:variable name="data" select="document('/path/to/xml')" />
<xsl:call-template name='build_string'>
<xsl:with-param name='data' select='$data' />
</xsl:call-template>
</xsl:template>
<!-- here is where i need help -->
<xsl:template name="build_string">
<xsl:param name='data'>
<xsl:value-of select='name($data/.)' />=<xsl:value-of select='$data/@value' />
<xsl:if test='$data/following-sibling::node()'>
<xsl:text>&</xsl:text>
<xsl:call-template name="build_str">
<xsl:with-param name="data" select='$nodes/following-sibling::node()' />
</xsl:call-template>
</xsl:if>
</xsl:template>
This almost works but it also prints text nodes from the input file and I don't want to match text nodes..
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/*/*">
<xsl:value-of select="concat(name(),'=',@value)"/>
<xsl:if test="not(position()=last())">
<xsl:text>&</xsl:text>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<args>
<sometag value="abc"/>
<anothertag value="def"/>
<atag value="blah"/>
</args>
produces the wanted, correct result:
sometag=abc&anothertag=def&atag=blah
I ended up realizing I could just use a for-each loop.. I'm not sure why I didnt use that to begin with. I'm still wondering how I could recursively iterate a list of adjacent nodes the way I was doing before (which wasn't working correctly because it was also catching text nodes and doing other weird things I couldn't understand). Here is my solution (I also added a separator variable)
<xsl:template name='string_builder'>
<xsl:param name='data' />
<xsl:param name='separator' />
<xsl:for-each select='$data/*'>
<xsl:value-of select='name()'/>=<xsl:value-of select='@value'/>
<xsl:if test='position() != last()'>
<xsl:value-of select='$separator'/>
</xsl:if>
</xsl:for-each>
</xsl:template>
精彩评论