如何在转换XML时保留命名空间?

时间:2016-02-09 06:02:06

标签: xml xslt

我试图转换输入XML以去除不需要的节点,同时在它们已经存在的所有节点上保留命名空间引用。我已经将我的XSL框起来了,但是我不确定为什么不保留输出XML上的命名空间。以下是输入XML,用于转换的XSL和输出XML。

输入XML如下:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <FullOrderResponse xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns="http://schemas.argility.com/NorthwindMetadata" preserveSpace="no"
        qAccess="0">
        <record xmlns="http://schemas.argility.com/NorthwindMetadata">
            <oldRecord>
                <FullOrder xmlns="http://schemas.argility.com/NorthwindMetadata">
                    <Header>
                        <OrderID>10248</OrderID>
                        <CustomerID>VINET</CustomerID>
                        <EmployeeID>5</EmployeeID>
                        <OrderDate>1996-07-04T00:00:00.0</OrderDate>
                        <RequiredDate>1996-08-01T00:00:00.0</RequiredDate>
                        <ShippedDate>1996-07-16T00:00:00.0</ShippedDate>
                        <ShipVia>3</ShipVia>
                        <Freight>32.38</Freight>
                        <ShipName>Vins et alcools Chevalier</ShipName>
                        <ShipAddress>59 rue de l'Abbaye</ShipAddress>
                        <ShipCity>Reims</ShipCity>
                        <ShipRegion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                            null="true" xsi:nil="true" />
                        <ShipPostalCode>51100</ShipPostalCode>
                        <ShipCountry>France</ShipCountry>
                    </Header>
                    <Lines>
                        <OrderID>10248</OrderID>
                        <ProductID>11</ProductID>
                        <UnitPrice>14</UnitPrice>
                        <Quantity>12</Quantity>
                        <Discount>0</Discount>
                    </Lines>
                    <CustomerID>VINET</CustomerID>
                </FullOrder>
            </oldRecord>
        </record>
    </FullOrderResponse>
</data>

输出XML(必需/期望)如下:

<?xml version="1.0" encoding="UTF-8"?>
<data>
    <FullOrderResponse xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
        xmlns="http://schemas.argility.com/NorthwindMetadata" preserveSpace="no"
        qAccess="0">
        <record xmlns="http://schemas.argility.com/NorthwindMetadata">
            <oldRecord>
                <FullOrder xmlns="http://schemas.argility.com/NorthwindMetadata">
                    <CustomerID>VINET</CustomerID>
                    <OrderID>10248</OrderID>
                    <CustomerID>VINET</CustomerID>
                    <EmployeeID>5</EmployeeID>
                    <OrderDate>1996-07-04T00:00:00.0</OrderDate>
                    <RequiredDate>1996-08-01T00:00:00.0</RequiredDate>
                    <ShippedDate>1996-07-16T00:00:00.0</ShippedDate>
                    <ShipVia>3</ShipVia>
                    <Freight>32.3800</Freight>
                    <ShipName>Vins et alcools Chevalier</ShipName>
                    <ShipAddress>59 rue de l'Abbaye</ShipAddress>
                    <ShipCity>Reims</ShipCity>
                    <ShipRegion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        null="true" xsi:nil="true" />
                    <ShipPostalCode>51100</ShipPostalCode>
                    <ShipCountry>France</ShipCountry>
                    <OrderID>10248</OrderID>
                    <ProductID>11</ProductID>
                    <UnitPrice>14.0000</UnitPrice>
                    <Quantity>12</Quantity>
                    <Discount>0.0</Discount>
                </FullOrder>
            </oldRecord>
        </record>
    </FullOrderResponse>
</data>

我已尝试使用以下问题中提供的解决方案,但我不确定它是否适用于我的情况。参考已经就此主题提出的旧问题,here。任何关于此的帮助/提示/建议都非常感谢

我为实现所需输出XML而构建的XSL如下:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:SOAP="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:nw="http://schemas.argility.com/NorthwindMetadata">
    <xsl:output method="xml" omit-xml-declaration="yes" indent="yes" />
    <xsl:strip-space elements="*" />

    <xsl:variable name="vNamespace"
        select="document('')/*/namespace::*[name()='nw']" />

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

    <xsl:template match="nw:Header">
        <xsl:apply-templates />
    </xsl:template>
    <xsl:template match="nw:Lines">
        <xsl:apply-templates />
    </xsl:template>
</xsl:stylesheet>

1 个答案:

答案 0 :(得分:1)

恕我直言,您需要做的就是:

XSLT 1.0

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:nw="http://schemas.argility.com/NorthwindMetadata">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="nw:Header | nw:Lines">
    <xsl:apply-templates />
</xsl:template>

</xsl:stylesheet>

注意

  1. 此:

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

    与XML中的任何内容都不匹配,因此不会应用。 也没有必要。

  2. 在您的输入中,有一个冗余的命名空间声明 record元素:

    <record xmlns="http://schemas.argility.com/NorthwindMetadata">
    

    父元素FullOrderResponse已经声明为相同 namespace作为默认名称空间。所以你可以期待 XSLT处理器去除冗余声明并让record 继承其父级声明的默认命名空间。