Я новичок в XSL/XML, и мне нужна помощь с преобразованием XSL. В моей задаче мне нужно преобразовать файл UBL в PUF.
Например, у меня есть этот XML:
<?xml version = "1.0" encoding = "UTF-8"?>
<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">
<cbc:ID>TOSL108</cbc:ID>
<cbc:IssueDate>2011-09-22</cbc:IssueDate>
<cac:InvoicePeriod>
<cbc:StartDate>2011-08-01</cbc:StartDate>
<cbc:EndDate>2011-08-31</cbc:EndDate>
</cac:InvoicePeriod>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PartyName>
<cbc:Name>Custom Cotter Pins</cbc:Name>
</cac:PartyName>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PartyName>
<cbc:Name>North American Veeblefetzer</cbc:Name>
</cac:PartyName>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:LegalMonetaryTotal>
<cbc:PayableAmount currencyID = "CAD">100.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:LineExtensionAmount currencyID = "CAD">100.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>Cotter pin, MIL-SPEC</cbc:Description>
</cac:Item>
</cac:InvoiceLine>
</Invoice>
И мне нужно создать файл с некоторыми пространствами имен pagero в корневом элементе. Мой ожидаемый результат:
<Invoice xmlns = "urn:pagero:PageroUniversalFormat:Invoice:1.0"
xmlns:cac = "urn:pagero:CommonAggregateComponents:1.0"
xmlns:cbc = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:puf = "urn:pagero:ExtensionComponent:1.0"
xmlns:ext = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
<cbc:CustomizationID>urn:pagero.com:puf:billing:2.0</cbc:CustomizationID>
<cbc:ProfileID>urn:pagero.com:puf:billing:1.0</cbc:ProfileID>
<cbc:ID>TOSL108</cbc:ID>
<cbc:IssueDate>2011-09-22</cbc:IssueDate>
<cac:InvoicePeriod>
<cbc:StartDate>2011-08-01</cbc:StartDate>
<cbc:EndDate>2011-08-31</cbc:EndDate>
</cac:InvoicePeriod>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PartyName>
<cbc:Name>Custom Cotter Pins</cbc:Name>
</cac:PartyName>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PartyName>
<cbc:Name>North American Veeblefetzer</cbc:Name>
</cac:PartyName>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:LegalMonetaryTotal>
<cbc:PayableAmount currencyID = "CAD">100.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:LineExtensionAmount currencyID = "CAD">100.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>Cotter pin, MIL-SPEC</cbc:Description>
</cac:Item>
</cac:InvoiceLine>
</Invoice>
Для этого я использую шаблон XSL, такой как UBLtoPUF.xsl. Проблема в том, что результирующий файл выглядит так:
<Invoice xmlns = "urn:pagero:PageroUniversalFormat:Invoice:1.0"
xmlns:cac = "urn:pagero:CommonAggregateComponents:1.0"
xmlns:cbc = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:puf = "urn:pagero:ExtensionComponent:1.0"
xmlns:ext = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
<cbc:CustomizationID>urn:pagero.com:puf:billing:2.0</cbc:CustomizationID>
<cbc:ProfileID>urn:pagero.com:puf:billing:1.0</cbc:ProfileID>
<cbc:ID xmlns = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">TOSL108</cbc:ID>
<cbc:IssueDate xmlns = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">
2011-09-22</cbc:IssueDate>
<cac:InvoicePeriod
xmlns:cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:StartDate>2011-08-01</cbc:StartDate>
<cbc:EndDate>2011-08-31</cbc:EndDate>
</cac:InvoicePeriod>
<cac:AccountingSupplierParty
xmlns:cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cac:Party>
<cac:PartyName>
<cbc:Name>Custom Cotter Pins</cbc:Name>
</cac:PartyName>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty
xmlns:cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cac:Party>
<cac:PartyName>
<cbc:Name>North American Veeblefetzer</cbc:Name>
</cac:PartyName>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:LegalMonetaryTotal
xmlns:cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:PayableAmount currencyID = "CAD">100.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine
xmlns:cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2">
<cbc:ID>1</cbc:ID>
<cbc:LineExtensionAmount currencyID = "CAD">100.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>Cotter pin, MIL-SPEC</cbc:Description>
</cac:Item>
</cac:InvoiceLine>
</Invoice>
На xmlns:cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" дочерних узлах появились <Invoice> пространства имен.
Эти пространства имен распространяются ТОЛЬКО через прямые /Invoice дочерние узлы, но не через другие дочерние узлы и т. д.
Так что я делаю все правильно (как-то) на всех детях детей и т. д., но НЕ на прямых детях /Invoice.
Есть шаблон, который я использую:
<?xml version = "1.0" encoding = "utf-8"?>
<xsl:stylesheet version = "1.0" xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:cac = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:puf = "urn:pagero:ExtensionComponent:1.0"
xmlns:ext = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns = "urn:pagero:PageroUniversalFormat:Invoice:1.0">
<xsl:output method = "xml" indent = "yes" />
<xsl:template match = "/">
<Invoice xmlns:cac = "urn:pagero:CommonAggregateComponents:1.0"
xmlns:cbc = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:puf = "urn:pagero:ExtensionComponent:1.0"
xmlns:ext = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2">
<cbc:CustomizationID>urn:pagero.com:puf:billing:2.0</cbc:CustomizationID>
<cbc:ProfileID>urn:pagero.com:puf:billing:1.0</cbc:ProfileID>
<xsl:apply-templates
select = "//*[local-name() = 'Invoice']/*[not(namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2')]" />
</Invoice>
</xsl:template>
<xsl:template
match = "//*[local-name() = 'Invoice']/*[namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2']">
<xsl:element name = "{name()}" namespace = "">
<xsl:apply-templates
select = "node()/*[not(namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2')]" />
</xsl:element>
</xsl:template>
<!-- Suppress the UBLVersionID element -->
<xsl:template match = "//*[local-name() = 'UBLVersionID']" />
<!-- Copy attributes as-is, except for the namespace attributes -->
<xsl:template
match = "@*[not(namespace-uri() = 'http://www.w3.org/2001/XMLSchema-instance')]
[not(namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2')]
[not(namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2')]
[not(namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2')]
[not(namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2')]">
<xsl:copy />
</xsl:template>
<!-- Copy elements as-is -->
<xsl:template match = "node()">
<xsl:copy>
<xsl:apply-templates
select = "@*[not(namespace-uri() = 'http://www.w3.org/2001/XMLSchema-instance')]
[not(namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2')]
[not(namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2')]
[not(namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:Invoice-2')]
[not(namespace-uri() = 'urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2')]" />
<xsl:apply-templates
select = "node()" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Пробовал менять <xsl:template match = "node()"> но не помогает. Я не нашел вопросов, как исключить пространства имен с помощью шаблона.
Пожалуйста, помогите мне, как я могу изменить свой шаблон, чтобы избавиться от этих пространств имен <Invoice> дочерних элементов?
Также я не вижу элемента UBLVersionID во входных данных?
@ michael.hor257k michael.hor257k Я редактировал, ожидаемый результат - второй блок xml.





AFAICT, вы хотите сделать просто:
XSLT 1.0
<xsl:stylesheet version = "1.0"
xmlns:xsl = "http://www.w3.org/1999/XSL/Transform"
xmlns:cac = "urn:pagero:CommonAggregateComponents:1.0"
xmlns:cbc = "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:puf = "urn:pagero:ExtensionComponent:1.0"
xmlns:ext = "urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns:inv = "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac0 = "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
exclude-result-prefixes = "inv cac0">
<xsl:output method = "xml" version = "1.0" encoding = "UTF-8" indent = "yes"/>
<xsl:strip-space elements = "*"/>
<xsl:template match = "*">
<xsl:element name = "{name()}">
<xsl:copy-of select = "@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
<xsl:template match = "/inv:Invoice">
<Invoice xmlns = "urn:pagero:PageroUniversalFormat:Invoice:1.0">
<xsl:apply-templates/>
</Invoice>
</xsl:template>
<xsl:template match = "cac0:*">
<xsl:element name = "cac:{local-name()}">
<xsl:copy-of select = "@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Я пропустил эту часть:
<!-- Suppress the UBLVersionID element -->
<xsl:template match = "//*[local-name() = 'UBLVersionID']" />
потому что я не вижу элемента UBLVersionID во входных данных. Плохая практика — полагаться исключительно на локальное имя элемента — esp. в XML с большим пространством имен, таком как ваш ввод. Вы должны использовать полное имя.
Вам необходимо понять правила для пространств имен для сконструированных элементов.
Во-первых, помните, что модель данных полностью посвящена пространствам имен в области видимости, а не объявлениям пространств имен. Элемент имеет набор привязок пространства имен (сопоставления префикса и uri), которые находятся в области действия этого элемента; не имеет значения, было ли пространство имен объявлено для этого элемента или для какого-либо предка. Таким образом, избыточное объявление пространства имен в элементе Invoice таблицы стилей, когда оно уже объявлено в элементе xsl:stylesheet, бессмысленно.
Когда придет время сериализовать результирующее дерево, сериализатор сгенерирует объявления пространств имен, чтобы были объявлены все пространства имен в области видимости (и только пространства имен в области видимости) для элементов результирующего дерева, устраняя избыточные объявления.
Существует три способа создания элементов, и у них есть разные правила того, какие привязки пространства имен в области видимости будут присутствовать в новом элементе:
Буквальный элемент результата (например, <Invoice>) копирует все привязки пространств имен в области видимости из таблицы стилей в дерево результатов, кроме тех, которые исключены в силу exclude-result-prefixes. Он также добавляет любые пространства имен, которые могут понадобиться для имен атрибутов элемента.
Инструкция xsl:element создает новый элемент с минимальным набором пространств имен в области видимости, необходимых для имен элемента и его атрибутов.
Инструкция xsl:copy или xsl:copy-of копирует привязки пространства имен в области действия из исходного элемента, который вы копируете.
Итак, если вы посмотрите на пространства имен, которые вы получаете для элемента cbc:ID в вашем результирующем документе (например), мне кажется, что этот элемент был создан с использованием инструкции xsl:copy, поэтому вам нужно понимать, что xsl:copy копирует пространства имен в области видимости. копируемого элемента исходного дерева.
В XSLT 2.0 есть атрибут <xsl:copy copy-namespaces = "no">, но в 1.0, если вы хотите отказаться от привязки пространств имен, вам нужно переключиться с xsl:copy на xsl:element.
Спасибо за пояснение, теперь мне стало понятнее!
Пожалуйста, отредактируйте свой вопрос и добавьте точный ожидаемый результат.