使用 XSLT 更改根元素和命名空间,但保留其他公共命名空间

问题描述 投票:0回答:1

我正在尝试将 XML 文档转换为具有新根元素的文档,但该文档共享许多其他公共元素名称空间。我在命名空间转换方面遇到麻烦。

这是输入 XML:

<CreditNote
      xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
      xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
      xmlns="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2">
   <cbc:CustomizationID>12345</cbc:CustomizationID>
   <cbc:ProfileID>67890</cbc:ProfileID>
   <cbc:ID>abcdef</cbc:ID>
   <cac:BillingReference>
      <cac:InvoiceDocumentReference>
         <cbc:ID>ghijk</cbc:ID>
         <cbc:IssueDate>2024-08-05</cbc:IssueDate>
      </cac:InvoiceDocumentReference>
   </cac:BillingReference>
</CreditNote>

这是我想要的输出 XML:

<?xml version="1.0" encoding="UTF-8"?>
<ubl:Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
             xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
             xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
             xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
   <cbc:ID>abcdef</cbc:ID>
   <cac:BillingReference>
      <cac:InvoiceDocumentReference>
         <cbc:ID>ghijk</cbc:ID>
      </cac:InvoiceDocumentReference>
   </cac:BillingReference>
</ubl:Invoice>

根节点(或命名空间)旨在从“urn:oasis:names:specation:ubl:schema:xsd:CreditNote-2”切换到“urn:oasis:names:specation:ubl:schema:xsd:Invoice-” 2”,同时共享公共命名空间:

cac
cbc

我正在使用 XSLT 3.0 和 SAXON-HE 12.4。这是我的 XLST。我从这篇文章中得到了一些提示:XSLT 重命名合格的根元素,保留其他名称空间

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="3.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
                xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
                xmlns:cn="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
                xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
                xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
                exclude-result-prefixes="cn">

   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/cn:CreditNote">
      <ubl:Invoice
            xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
            xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
            xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
            xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
         <xsl:apply-templates select="cbc:ID"/>
         <xsl:apply-templates select="cac:BillingReference"/>
      </ubl:Invoice>
   </xsl:template>

   <!-- 
      Identity template, provides default behavior that copies all content into 
      the output Do not copy namespace attributes into elements.
    -->
   <xsl:template match="@* | node()">
      <xsl:copy copy-namespaces="no">
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
   </xsl:template>

   <!-- 
      Copy all elements from the CreditNote namespace, but change the namespace 
      to the default namespace (Invoice).
    -->
   <xsl:template match="cn:*">
      <xsl:element name="{local-name()}">
         <xsl:apply-templates select="@*|node()"/>
      </xsl:element>
   </xsl:template>

   <xsl:template match="*/cac:BillingReference">
      <xsl:copy>
         <xsl:copy-of select="namespace::*[not(. = ('urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2'))]"/>
         <xsl:apply-templates select="cac:InvoiceDocumentReference"/>
      </xsl:copy>
   </xsl:template>

</xsl:stylesheet>

这是我得到的输出 XML:

<?xml version="1.0" encoding="UTF-8"?>
<ubl:Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
             xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
             xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
             xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
   <cbc:ID>abcdef</cbc:ID>
   <cac:BillingReference xmlns="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2">
      <cac:InvoiceDocumentReference>
         <cbc:ID>ghijk</cbc:ID>
         <cbc:IssueDate>2024-08-05</cbc:IssueDate>
      </cac:InvoiceDocumentReference>
   </cac:BillingReference>
</ubl:Invoice>

我知道 XSLT 正在尝试保留源命名空间,但我不清楚为什么我的 XSLT 没有解决这个问题。

  1. 如何防止它在选择的模板上输出
    xmlns="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
  2. 为什么
    cac:BillingReference
    模板未匹配? (应该已经修剪过
    cbc:IssueDate
    。)
xml xslt namespaces xml-namespaces xslt-3.0
1个回答
0
投票

我认为以下就足够了:

<xsl:stylesheet version="3.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
                xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
                xmlns:cn="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
                xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
                xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
                exclude-result-prefixes="cn">

   <xsl:output method="xml" indent="yes"/>

   <xsl:template match="/cn:CreditNote">
      <ubl:Invoice
            xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
            xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
            xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
            xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
         <xsl:apply-templates select="cbc:ID"/>
         <xsl:apply-templates select="cac:BillingReference"/>
      </ubl:Invoice>
   </xsl:template>

   <!-- 
      Identity template, provides default behavior that copies all content into 
      the output Do not copy namespace attributes into elements.
    -->
   <xsl:template match="@* | node()">
      <xsl:copy copy-namespaces="no">
         <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
   </xsl:template>

   <xsl:template match="cbc:IssueDate"/>

</xsl:stylesheet>

撒克逊 HE 小提琴示例

© www.soinside.com 2019 - 2024. All rights reserved.