我得到了一个XML,我将其转换为另一个,但在翻译之后,我得到了一些具有空命名空间声明(xmlns=""
)的元素,我想删除它。
其次,我还希望在xmlns:xsi
元素中声明InterChangeHead
。
INPUT 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>
CURRENT 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>
答案 0 :(得分:2)
请记住,xmlns="..."
声明为其附加的元素及其所有后代设置默认命名空间,除非在树的另一个xmlns="..."
处反对。因此,在您想要的输出中,<InterChangeHead xmlns="posten.xsd" >
下的所有后代元素也位于posten.xsd
命名空间中,您的模板需要反映这一点。由于您使用的是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
,正确设置名称空间。
答案 1 :(得分:0)
您需要更改每个元素节点的名称空间,因此请更改模板
<!-- 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>
到
<!-- Correct InterChangeHead element and descendants -->
<xsl:template match="InterChangeHead | InterChangeHead//*">
<xsl:element name="{local-name()}" namespace="posten.xsd">
<!-- Copy childs -->
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>
这是一个简化代码的完整样式表:
<?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>
<!-- Correct InterChangeHead element -->
<xsl:template match="InterChangeHead | InterChangeHead//*">
<xsl:element name="{local-name()}" namespace="posten.xsd">
<!-- Copy childs -->
<xsl:apply-templates select="@* | node()" />
</xsl:element>
</xsl:template>
<!-- Rename elements beginning with "he" to elements without the "he" -->
<xsl:template match="InterChangeHead//*[substring(local-name(), 1, 2) = 'he']" priority="5">
<xsl:element name="{substring(local-name(), 3)}" namespace="posten.xsd">
<xsl:apply-templates select="@*|node()" />
</xsl:element>
</xsl:template>
<!-- Remove type attribute -->
<xsl:template match="@type"/>
<!-- Remove unnecessary elements -->
<xsl:template match="heXmlnsxsi" priority="6"/>
<xsl:template match="heXmlns" priority="6"/>
</xsl:stylesheet>