2

我得到了一个 XML,我将其转换为另一个,但在翻译之后,我得到了一些具有空命名空间声明 ( xmlns="") 的元素,我想删除这些元素。

其次,我还希望在元素中xmlns:xsi声明。InterChangeHead

输入 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>
4

2 回答 2

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>

I have added a specific template to declare the xsi namespace on InterChangeHead, though I'm not sure why it's necessary to include that declaration as it isn't used anywhere in the output XML document. If it turns out not to be necessary you can simply remove the <xsl:template match="InterChangeHead"> altogether, as the template matching * will also handle InterChangeHead, setting the namespace correctly.

于 2013-04-08T11:33:15.903 回答
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>
于 2013-04-08T11:22:56.027 回答