我是 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>
子元素的命名空间?
您需要了解构造元素的命名空间规则。
首先记住数据模型是关于范围内命名空间的,而不是关于命名空间声明的。一个元素有一组在该元素范围内的名称空间绑定(前缀-uri 映射);名称空间是在该元素上还是在某个祖先上声明并不重要。因此,当它已经在
Invoice
元素上声明时,在样式表中的 xsl:stylesheet
元素上冗余声明命名空间是没有意义的。
当需要序列化结果树时,序列化程序将生成命名空间声明,以便声明结果树中元素上的所有in-scope命名空间(并且仅in-scope命名空间),从而消除冗余声明.
有三种创建元素的方法,它们对于新元素上将出现哪些范围内命名空间绑定有不同的规则:
文字结果元素(如
<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
。
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: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
元素。仅依赖元素的本地名称是不好的做法 - 特别是。在重命名空间的 XML 中,例如您的输入。您应该使用完全限定的名称。