仅复制第一个子元素以输出

时间:2016-08-30 14:46:16

标签: xslt

我的源xml具有相同标记名称的不同节点。我想将这个xml转换为xml,其中每个子节点都是唯一的,例如:这是我的xml:

<?xml version="1.0" encoding="utf-16"?>
<shiporder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" orderid="orderid1">
  <orderperson>orderperson1</orderperson>
  <shipto>
    <name>name1</name>
    <address>address1</address>
    <city>city1</city>
    <country>country1</country>
  </shipto>
  <item>
    <title>title1</title>
    <note>note1</note>
    <note>1</note>
  </item>
  <item>
    <title>title2</title>
    <note>note2</note>
  </item>
</shiporder>

转换后的结果应如下所示:

<?xml version="1.0" encoding="utf-16"?>
<shiporder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" orderid="orderid1">
  <orderperson>orderperson1</orderperson>
  <shipto>
    <name>name1</name>
    <address>address1</address>
    <city>city1</city>
    <country>country1</country>
  </shipto>
  <item>
    <title>title1</title>
    <note>note1</note>
  </item>
</shiporder>

我试图通过*[1]选择第一个孩子,如果有一个标签名称相同但是到目前为止我没有得到正确的结果:

<xsl:template match="/">
        <xsl:copy-of select="//*[1]"/>
</xsl:template>

1 个答案:

答案 0 :(得分:1)

使用XSLT 2.0,您可以尝试

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:key name="name" match="*" use="node-name(.)"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[not(. is key('name', node-name(.), ..)[1])]"/>

</xsl:stylesheet>

应该对您显示的样本执行此操作。另一方面,如果可以嵌套相同名称的元素,则需要使用不同的模式:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="2.0">

    <xsl:strip-space elements="*"/>
    <xsl:output indent="yes"/>

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="*[preceding-sibling::*[node-name(.) eq node-name(current())]]"/>

</xsl:stylesheet>