Xslt 2将非唯一元素转换为网格属性

时间:2014-12-17 15:06:13

标签: xml xslt-2.0

我有一个具有此结构的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合作

1 个答案:

答案 0 :(得分:1)

如果您要为每个元素创建一个属性,它肯定会覆盖您创建的任何先前属性(使用相同的名称)。

您将此标记为XSLT 2.0,因此这是一个2.0选项。输出并不完全匹配你的输出;你的例子在几个地方都没有多大意义。 (例如,为什么第一个levellaydown="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>