我有一个具有此结构的XML文件
<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>
我需要将其转换为类似的内容以在网格中显示
<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">
我发现xslt有效,但不是元素非唯一的地方。他们只获取最后一个元素,表明每个元素都覆盖了之前的元素。没有包括它,因为我宁愿看到正确的解决方案,而不是我刚才提出的工作尝试。我是一个xsl / xslt新手,所以任何注释都会有所帮助。我与vs 2013合作
答案 0 :(得分:1)
如果您要为每个元素创建一个属性,它肯定会覆盖您创建的任何先前属性(使用相同的名称)。
您将此标记为XSLT 2.0,因此这是一个2.0选项。输出并不完全匹配你的输出;你的例子在几个地方都没有多大意义。 (例如,为什么第一个level
有laydown="3"
而不是laydown="4"
而level
都有qd="NE"
。)
XML输入
<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>
<强>输出强>
<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>