我得到了一个 XML,我将其转换为另一个 XML,但在翻译后,我得到了一些具有空 namespace 声明 (xmlns=""
) 的元素,我想将其删除。
其次,我还希望在 InterChangeHead
元素中声明 xmlns:xsi
。
输入 XML
<?xml version="1.0" encoding="UTF-8"?>
<PostenInterchange type="tag">
<heInterchangeType>PostenInterchange</heInterchangeType>
<heVersion>1.4-rev3</heVersion>
<heTestindicator>1</heTestindicator>
<InterChangeHead type="tag">
<heVersion>1</heVersion>
<heSenderid>SENDID</heSenderid>
<heRecipientid>RECIPID</heRecipientid>
<heXmlnsxsi>"http://www.w3.org/2001/XMLSchema-instance"</heXmlnsxsi>
<heXmlns>"posten.xsd"</heXmlns>
<Shipment type="tag">
<heShipmenttype>IMP</heShipmenttype>
<Shipper type="tag">
<name>Shipper</name>
</Shipper>
<Consignee type="tag">
<name>Consignee</name>
</Consignee>
<GoodsData type="tag">
<heSequencenumber>2</heSequencenumber>
<GrossWeight>0.000</GrossWeight>
<NetWeight>0.660</NetWeight>
</GoodsData>
</Shipment>
</InterChangeHead>
</PostenInterchange>
当前 XSLT
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" exclude-result-prefixes="xs fn">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- Identity template -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:template>
<!-- Copy local names -->
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates select="@*|node()" />
</xsl:element>
</xsl:template>
<!-- Rename elements beginning with "he" to elements without the "he" -->
<xsl:template match="node()">
<xsl:choose>
<xsl:when test="substring(local-name(), 1, 2) = 'he'">
<xsl:element name="{substring(local-name(), 3)}">
<xsl:apply-templates select="@*|node()" />
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="@*|node()" />
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Correct InterChangeHead element -->
<xsl:template match="InterChangeHead">
<xsl:element name="InterChangeHead" namespace="posten.xsd">
<!-- Copy childs -->
<xsl:apply-templates select="child::node()" />
</xsl:element>
</xsl:template>
<!-- Remove type attribute -->
<xsl:template match="@type"/>
<!-- Remove unnecessary elements -->
<xsl:template match="heXmlnsxsi" />
<xsl:template match="heXmlns" />
</xsl:stylesheet>
电流输出
<?xml version="1.0" encoding="UTF-8"?>
<PostenInterchange>
<InterchangeType>PostenInterchange</InterchangeType>
<Version>1.4-rev3</Version>
<Testindicator>1</Testindicator>
<InterChangeHead xmlns="posten.xsd">
<Version xmlns="">1</Version>
<Senderid xmlns="">SENDID</Senderid>
<Recipientid xmlns="">RECIPID</Recipientid>
<Shipment xmlns="">
<Shipmenttype>IMP</Shipmenttype>
<Shipper>
<name>Shipper</name>
</Shipper>
<Consignee>
<name>Consignee</name>
</Consignee>
<GoodsData>
<Sequencenumber>2</Sequencenumber>
<GrossWeight>0.000</GrossWeight>
<NetWeight>0.660</NetWeight>
</GoodsData>
</Shipment>
</InterChangeHead>
</PostenInterchange>
期望输出
<?xml version="1.0" encoding="UTF-8"?>
<PostenInterchange>
<InterchangeType>PostenInterchange</InterchangeType>
<Version>1.4-rev3</Version>
<Testindicator>1</Testindicator>
<InterChangeHead xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="posten.xsd" >
<Version>1</Version>
<Senderid>SENDID</Senderid>
<Recipientid>RECIPID</Recipientid>
<Shipment>
<Shipmenttype>IMP</Shipmenttype>
<Shipper>
<name>Shipper</name>
</Shipper>
<Consignee>
<name>Consignee</name>
</Consignee>
<GoodsData>
<Sequencenumber>2</Sequencenumber>
<GrossWeight>0.000</GrossWeight>
<NetWeight>0.660</NetWeight>
</GoodsData>
</Shipment>
</InterChangeHead>
</PostenInterchange>
谁能帮我完成最后一点吗?我添加了下一个模板,因为我认为这将删除空的命名空间声明:
<!-- Copy local names -->
<xsl:template match="*">
<xsl:element name="{name()}">
<xsl:apply-templates select="@*|node()" />
</xsl:element>
</xsl:template>
最佳答案
请记住 xmlns="..."
声明为其所附加的元素及其所有后代设置默认命名空间,除非被另一个 xmlns="..."
取消。再往树下走。因此,在您所需的输出中 <InterChangeHead xmlns="posten.xsd" >
下的所有后代元素也在 posten.xsd
命名空间,并且您的模板需要反射(reflect)这一点。由于您使用的是 XSLT 2.0,因此您可以使用条件作为 XPath 表达式的一部分来轻松完成此操作:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- Copy elements, fixing up names and namespaces as required -->
<xsl:template match="*">
<xsl:element name="{if(substring(local-name(), 1, 2) = 'he')
then substring(local-name(), 3) else local-name()}"
namespace="{if(ancestor-or-self::InterChangeHead)
then 'posten.xsd' else ''}">
<xsl:apply-templates select="@*|node()" />
</xsl:element>
</xsl:template>
<!-- specific template for InterChangeHead to add the (unused) xsi
namespace declaration -->
<xsl:template match="InterChangeHead">
<InterChangeHead xmlns="posten.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:apply-templates select="@*|node()" />
</InterChangeHead>
</xsl:template>
<xsl:template match="@* | text()">
<xsl:copy-of select="." />
</xsl:template>
<!-- Remove type attribute -->
<xsl:template match="@type"/>
<!-- Remove unnecessary elements -->
<xsl:template match="heXmlnsxsi" />
<xsl:template match="heXmlns" />
</xsl:stylesheet>
我添加了一个特定的模板来声明 xsi
InterChangeHead
上的命名空间,但我不确定为什么需要包含该声明,因为它在输出 XML 文档中的任何地方都没有使用。如果事实证明没有必要,您可以简单地删除 <xsl:template match="InterChangeHead">
总共,作为模板匹配 *
还将处理InterChangeHead
,正确设置命名空间。
关于xml - 删除元素中的空命名空间声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15877544/