【问题标题】:How to preserve the namespaces while transforming an XML?如何在转换 XML 时保留名称空间?
【发布时间】:2016-02-09 06:02:06
【问题描述】:

我正在尝试转换输入 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>

我尝试使用在 SO 上提出的以下问题中提供的解决方案,但我不确定它是否适用于我的情况。参考关于这个主题的老问题,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>

【问题讨论】:

    标签: xml xslt


    【解决方案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 已声明相同 命名空间作为默认命名空间。因此,您可以期待 XSLT 处理器去除冗余声明并让record 继承其父级声明的默认命名空间。

    【讨论】:

    • 感谢您指出冗余
    • @BPavanKumar 默认命名空间(声明时未将其绑定到前缀)由所有后代元素继承(除非显式地被前缀覆盖)。例如,在您的输入 XML 中,oldRecord 元素与其父 record 位于同一命名空间中。将其更改为 &lt;oldRecord xmlns="http://schemas.argility.com/NorthwindMetadata"&gt; 不会改变任何内容。
    • 感谢您的解释,现在明白了! :)
    猜你喜欢
    • 1970-01-01
    • 2019-11-26
    • 2013-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-23
    • 1970-01-01
    相关资源
    最近更新 更多