XML to XML using XSL Problem
I'd like to convert an XML file into another XML file with a different structure using XSL and I'm kindda new to XSL. The input section of the XML goes like this:
<set>
<object> Value </object>
<name> Value </name>
<tag>
<event> Value </event>
<group> Value </group>
<other> Value </other>
</tag>
<object>
<object>...</object>
</set>
I would like the desired output to be:
<set>
<event>
<group>
<object name="value">
<tag>
<other> Value </other>
</tag>
</object>
<group>
<group>...</group>
<event>...</event&开发者_运维问答gt;
</set>
Meaning to say I'd like to search through the input xml and group the objects according to say the 'event' nodes followed by the 'group' nodes with the same value instead. Help?
If you're xslt processor supports exslt you could use set:distinct to loop over distinct events and distinct groups that have that event. I tested the following with xsltproc, but they should work in any processor that supports exslt:function. see: http://www.exslt.org/func/elements/function/index.html.
Please note that there is a bug in the implementation of set:distinct posted there that I've fixed for you here.
test.xslt:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:func="http://exslt.org/functions"
xmlns:set="http://exslt.org/sets"
extension-element-prefixes="func set">
<xsl:import href="set.distinct.function.xsl" />
<xsl:template match="set">
<set>
<xsl:variable name="set" select="."/>
<xsl:value-of select="count(object/tag/event)"/><xsl:text> </xsl:text>
<xsl:value-of select="count(set:distinct(object/tag/event))"/>
</xsl:for-each>
<xsl:for-each select="set:distinct(object/tag/event)">
<event>
<xsl:attribute name="name">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:variable name="event" select="." />
<xsl:for-each select="set:distinct($set/object/tag[event=$event]/group)">
<group>
<xsl:attribute name="name">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:variable name="group" select="." />
<xsl:apply-templates select="$set/object[tag/event=$event][tag/group=$group]" />
</group>
</xsl:for-each>
</event>
</xsl:for-each>
</set>
</xsl:template>
<xsl:template match="object">
<object name="{name}"/>
</xsl:template>
</xsl:stylesheet>
set.distinct.function.xsl:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/functions"
xmlns:set="http://exslt.org/sets"
extension-element-prefixes="exsl"
exclude-result-prefixes="set">
<exsl:function name="set:distinct">
<xsl:param name="nodes" select="/.." />
<xsl:choose>
<xsl:when test="not($nodes)">
<exsl:result select="/.." />
</xsl:when>
<xsl:otherwise>
<xsl:variable name="distinct"
select="set:distinct($nodes[position() > 1])" />
<exsl:result select="$distinct | $nodes[1][not(. = $distinct)]" />
</xsl:otherwise>
</xsl:choose>
</exsl:function>
</xsl:stylesheet>
test.xml:
<set>
<object>
<name> Value1 </name>
<tag>
<event> Value </event>
<group> Value </group>
<other> Value </other>
</tag>
</object>
<object>
<name> Value2 </name>
<tag>
<event> Value </event>
<group> Value2 </group>
<other> Value </other>
</tag>
</object>
<object>
<name> Value3 </name>
<tag>
<event> Value </event>
<group> Value2 </group>
<other> Value </other>
</tag>
</object>
<object>
<name> Value4 </name>
<tag>
<event> Value </event>
<group> Value </group>
<other> Value </other>
</tag>
</object>
<object>
<name> Value5 </name>
<tag>
<event> Value2 </event>
<group> Value </group>
<other> Value </other>
</tag>
</object>
<object>
<name> Value6 </name>
<tag>
<event> Value2 </event>
<group> Value </group>
<other> Value </other>
</tag>
</object>
</set>
精彩评论