问题
I have an XML file with this structure
<levels>
<level id="0" qd="NE">
<gate>99</gate>
<zone>2</zone>
<laydown>4</laydown>
</level>
<level id="0" qd="SE">
<gate>1</gate>
<zone>6</zone>
<laydown>1</laydown>
<laydown>2</laydown>
<laydown>3</laydown>
<zone>5</zone>
<zone>5</zone>
</level>
</levels>
And I need to convert it to something like this to display in a grid
<level id="0" qd="NE" gate="99" zone="2" laydown="3">
<level id="0" qd="NE" gate="1" zone="5,6" laydown="1,2,3">
I have found xslt that works but not where the elements are non-unique. They only pick up the LAST element suggesting that each element is overwriting the previous. Have not included it as I would rather see the proper solution than my bodged attempt just made to work. I am an xsl/xslt newbie so any annotation will be helpful. I work with vs 2013
回答1:
If you're creating an attribute for each element, it will definitely overwrite any previous attribute that you've created (with the same name).
You tagged this as XSLT 2.0, so here's a 2.0 option. The output doesn't match yours exactly; your example doesn't make a whole lot of sense in a couple of places. (Like why does the first level
have laydown="3"
instead of laydown="4"
and both level
's have qd="NE"
.)
XML Input
<levels>
<level id="0" qd="NE">
<gate>99</gate>
<zone>2</zone>
<laydown>4</laydown>
</level>
<level id="0" qd="SE">
<gate>1</gate>
<zone>6</zone>
<laydown>1</laydown>
<laydown>2</laydown>
<laydown>3</laydown>
<zone>5</zone>
<zone>5</zone>
</level>
</levels>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:local="local"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:function name="local:sort">
<xsl:param name="seq"/>
<xsl:perform-sort select="$seq">
<xsl:sort data-type="number"/>
</xsl:perform-sort>
</xsl:function>
<xsl:template match="level">
<xsl:variable name="level" select="."/>
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:for-each select="distinct-values(*/name())">
<xsl:attribute name="{.}"
select="string-join(distinct-values(local:sort($level/*[name()=current()])),',')"/>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Output
<levels>
<level id="0" qd="NE" gate="99" zone="2" laydown="4"/>
<level id="0" qd="SE" gate="1" zone="5,6" laydown="1,2,3"/>
</levels>
来源:https://stackoverflow.com/questions/27528580/xslt-2-convert-non-unique-elements-to-attributes-for-grid