0

我有一段 XML,如下所示:

<LISTOFHARDWARE>
    <HARDWARE>
        <item>
            <SERIALNUMBER>D4242050101</SERIALNUMBER>
            <STATUS>2 </STATUS>
            <STATUSREASON>998 </STATUSREASON>
            <MACADDRESS />
            <LINKEDSMARTCARD>4135237101</LINKEDSMARTCARD>
            <PRODUCTDETAIL>
                <TYPE>DEVICE</TYPE>
                <MODEL>ABC123</MODEL>
            </PRODUCTDETAIL>
        </item>
        <item>
            <SERIALNUMBER>D4242050101</SERIALNUMBER>
            <STATUS>2 </STATUS>
            <STATUSREASON>998 </STATUSREASON>
            <MACADDRESS />
            <LINKEDSMARTCARD>4135237101</LINKEDSMARTCARD>
            <PRODUCTDETAIL>
                <TYPE>DEVICE</TYPE>
                <MODEL>ABC123</MODEL>
            </PRODUCTDETAIL>
        </item>
    </HARDWARE>
</LISTOFHARDWARE>   

我希望将<item>元素替换为<HARDWARE>元素(直接父元素),并<HARDWARE>删除父元素,以便结果如下所示:

<LISTOFHARDWARE>
    <HARDWARE>
        <SERIALNUMBER>D4242050101</SERIALNUMBER>
        <STATUS>2 </STATUS>
        <STATUSREASON>998 </STATUSREASON>
        <MACADDRESS />
        <LINKEDSMARTCARD>4135237101</LINKEDSMARTCARD>
        <PRODUCTDETAIL>
            <TYPE>DEVICE</TYPE>
            <MODEL>ABC123</MODEL>
        </PRODUCTDETAIL>
    </HARDWARE>
    <HARDWARE>
        <SERIALNUMBER>D4242050101</SERIALNUMBER>
        <STATUS>2 </STATUS>
        <STATUSREASON>998 </STATUSREASON>
        <MACADDRESS />
        <LINKEDSMARTCARD>4135237101</LINKEDSMARTCARD>
        <PRODUCTDETAIL>
            <TYPE>DEVICE</TYPE>
            <MODEL>ABC123</MODEL>
        </PRODUCTDETAIL>

    </HARDWARE>
</LISTOFHARDWARE>   

有没有一种方法可以在 XSL 转换中执行此操作,该转换适用于任何包含<item>元素的 XML 文件?

编辑

在得到这个答案的帮助和进一步的研究之后,我几乎就在那里,但并不完全。考虑以下:

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="@*|node()">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" />
        </xsl:copy>
    </xsl:template>

    <!--  Replace <item> with name of parent element -->
    <xsl:template match="item">
        <xsl:element name="{name(..)}">
            <xsl:apply-templates select="@*|node()" />
        </xsl:element>
    </xsl:template>

    <!-- Remove immediate parent of <item> elements -->
    <xsl:template match="item/.."> <!-- Results in syntax error --> 
            <xsl:apply-templates select="@*|node()" />
    </xsl:template>

</xsl:stylesheet>

问题是,在成功将元素更改<item>为父元素的名称后,我无法item通过动态引用其父元素来删除任何元素的父元素。

4

3 回答 3

3

这是一种方法:

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

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

  <!-- Process any element that has "item" as child -->
  <xsl:template match="*[item]">
    <xsl:apply-templates/>
  </xsl:template>

  <!-- Replace "item" with its parent in source XML -->
  <xsl:template match="item">
    <xsl:element name="{name(..)}">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>
于 2013-09-19T13:00:05.353 回答
1

您首先需要了解身份转换,它可用于复制 XML 中不需要任何更改的所有节点

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

您需要简化您认为转换将如何工作的方式,因为您真正要说的是删除item元素,但保留其子元素。要做到这一点,只需另一个简单的模板后缀

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

所有这一切都在匹配item元素,然后只是继续处理它的子元素而不复制item元素本身(并且子节点只是被标识模板复制)。

试试这个 XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="item">
    <xsl:apply-templates select="@*|node()"/>
  </xsl:template>
</xsl:stylesheet>
于 2013-09-19T12:52:42.957 回答
1

那这个呢?

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" />

    <xsl:template match="/*">
        <xsl:element name="{node-name(.)}">
            <xsl:for-each select="*/item">
                <xsl:element name="{node-name(..)}">
                  <xsl:copy-of select="./*" />
                </xsl:element>
            </xsl:for-each>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>

由 OP 编辑​​:就我而言,我必须将函数更改node-name()name(),否则将无法编译。

于 2013-09-19T13:45:19.010 回答