我有一段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
元素的父级。
答案 0 :(得分: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>
答案 1 :(得分:1)
首先需要了解可用于复制XML中不需要任何更改的所有节点的Identity 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>
所有这一切都与 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>
答案 2 :(得分: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()
,否则无法编译。