我正在尝试编写一个样式表,它将对应于模式版本 1 的实例文档转换为模式的版本 2。大约有 300 个元素,所以我不想写一堆模板。版本之间的绝大多数差异是一系列标准重命名,例如删除前缀、在以小写结尾的单词和相邻单词之间删除下划线等。但是我还需要适应添加和删除元素。
<SentSequence>
后 <StatusCode>
<Line_Order>
<?xml version="1.0" encoding="UTF-8"?>
<Entries>
<Entry>
<Entry_Number>10158271304</Entry_Number>
<CHB_File>63475017024503000</CHB_File>
<Traffic_File>1017271467</Traffic_File>
<Status_Code>A</Status_Code>
<Header_Country_of_Origin>VN</Header_Country_of_Origin>
<Importer_or_Owner>Owner</Importer_or_Owner>
<Entry_Total_Additions_to_Value>.00</Entry_Total_Additions_to_Value>
<Entry_IRS_Excise_Tax>.00</Entry_IRS_Excise_Tax>
<Entry_AD_Duties>.00</Entry_AD_Duties>
<Entry_CV_Duties>.00</Entry_CV_Duties>
<Header_Parties>
<Header_Party>
<Header_Party_Type>Importer</Header_Party_Type>
</Header_Party>
</Header_Parties>
<Invoices>
<Invoice>
<Invoice_Order>1</Invoice_Order>
<Invoice_Lines>
<Invoice_Line>
<Line_Order>1</Line_Order>
<Line_Quantity>685</Line_Quantity>
<Entry_Lines>
<Entry_Line>
<CBP7501_Line>1</CBP7501_Line>
</Entry_Line>
</Entry_Lines>
</Invoice_Line>
</Invoice_Lines>
</Invoice>
</Invoices>
</Entry>
</Entries>
<?xml version="1.0" encoding="UTF-8"?>
<Entries>
<Entry>
<EntryNumber>10158271304</EntryNumber>
<CHB_File>63475017024503000</CHB_File>
<TrafficFile>1017271467</TrafficFile>
<StatusCode>A</StatusCode>
<SentSequence>1</SentSequence>
<CountryOrigin>VN</CountryOrigin>
<ImporterOrOwner>Owner</ImporterOrOwner>
<Entry_Total_Additions_to_Value>.00</Entry_Total_Additions_to_Value>
<IRS_ExciseTax>.00</IRS_ExciseTax>
<AD_Duties>.00</AD_Duties>
<CV_Duties>.00</CV_Duties>
<HeaderParties>
<HeaderParty>
<PartyType>Importer</PartyType>
</HeaderParty>
</HeaderParties>
<Invoices>
<Invoice>
<InvoiceOrder>1</InvoiceOrder>
<InvoiceLines>
<InvoiceLine>
<LineQuantity>685</LineQuantity>
<EntryLines>
<EntryLine>
<CBP7501Line>1</CBP7501_Line>
</EntryLine>
</EntryLines>
</InvoiceLine>
</InvoiceLines>
</Invoice>
</Invoices>
</Entry>
</Entries>
我发现了几种不同的处理重命名的方法,从使用函数(我最初的想法)到多个模板。我发现最有前途的方法是使用第二个样式表。我使用了源自例 8-9 的一个。在 O'Reilly 的 XSLT Cookbook 第二版中。但是我喜欢通用的外部,但无法让它工作。我使用的那个似乎最适合处理添加和重命名。但是我可以混合使用,因为指定所有重命名有点低效。就我而言,我在 Excel 电子表格中有文档,因此我使用它来生成映射样式表的内容。
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
xmlns:kn="http://us.customsbrokerage.net/kn/cb/xsd/v1.0/functions"
xmlns:ren="http://www.ora.com/namespaces/rename"
xmlns:cvt="my:convert"
exclude-result-prefixes="xs math xd"
version="3.0">
<!-- Mapping stylesheet -->
<cvt:convert>
<element rename="true" curName="Entry_Number" new="EntryNumber"/>
<element rename="true" curName="Traffic_File" new="TrafficFile"/>
<element rename="true" curName="Status_Code" new="StatusCode"/>
<element add="true" curName="Status_Code" new="SentSequence"/>
<element rename="true" curName="Header_Country_of_Origin" new="CountryOriginCode"/>
<element rename="true" curName="Importer_or_Owner" new="ImporterOrOwner"/>
<element rename="true" curName="Entry_Total_Additions_to_Value" new="TotalAdditions"/>
<element rename="true" curName="Entry_IRS_Excise_Tax" new="IRS_ExciseTax"/>
<element rename="true" curName="Entry_AD_Duties" new="AD_Duties"/>
<element rename="true" curName="Entry_CV_Duties" new="CV_Duties"/>
<element rename="true" curName="Header_Parties" new="HeaderParties"/>
<element rename="true" curName="Header_Party" new="HeaderParty"/>
<element rename="true" curName="Header_Party_Type" new="CBP_PartyType"/>
<element rename="true" curName="Invoice_Lines" new="InvoiceLines"/>
<element rename="true" curName="Invoice_Line" new="InvoiceLine"/>
<element rename="true" curName="Invoice_Order" new="InvoiceOrder"/>
<element rename="true" curName="Line_Order" new=""/>
<element rename="true" curName="Line_Quantity" new="LineQuantity"/>
<element rename="true" curName="Entry_Lines" new="EntryLines"/>
<element rename="true" curName="Entry_Line" new="EntryLine"/>
<element rename="true" curName="CBP7501_Line" new="CBP7501Line"/>
</cvt:convert>
<xsl:output method="xml" encoding="UTF-8" byte-order-mark="no" indent="true" version="1.0"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"*[name()=document('')/*/cvt:convert/element/@curName]">
<xsl:variable name="convertNode" select="*[name()=document('')/*/cvt:convert/element/@curName]"/>
<xsl:if test="$convertNode/@rename='true'">
<xsl:element name=
"{document('')/*/cvt:convert/element
[@curName=name(current())]
/@new}">
</xsl:element>
</xsl:if>
<xsl:if test="*[name()=document('')/*/cvt:convert/element/@curName]/@add=true()">
<xsl:element name=
"{document('')/*/cvt:convert/element
[@curName=name(current())]
/@new}">
</xsl:element>
</xsl:if>
<xsl:if test="*[name()=document('')/*/cvt:convert/element/@delete]=true()"/>
<xsl:apply-templates select="node()|@*"/>
</xsl:template>
</xsl:stylesheet>
在 SO 上与我最接近的问题似乎是在这里。但是我不明白该方法足以将其移植到我的案例中。此外,它还需要 XSLT 3.0 或使用 XSLT 2.0 的两步过程。我更喜欢使用 XSLT 2.0 的一步处理过程,但如果必须的话,我可以使用 XSLT 3.0。
为了供大家参考,我使用了 XSLT 3.0 方法并进行了以下更改。请参阅XSLT 3.0 解决方案更改。
添加了用于删除的 delete="true" 属性,并相应地使用 @new = '' 谓词更改了模板匹配。(<xsl:key name="del-ref" match="element[@delete = 'true']" use="@curName"/>
和<xsl:template match="*[key('del-ref', local-name(), $convert-map)]" priority="5"/>
)
修改 mode="new" 模板以处理同一现有节点之后的多个添加。添加xsl:choose
以处理添加多个 ( <xsl:when test="count(key('add-ref', local-name(), $convert-map))>1">
) 或只有一个 ( <xsl:otherwise>
) 的情况。使用xsl:for-each
指令迭代多个加法 (<xsl:for-each select="key('add-ref', local-name(), $convert-map)">
和<xsl:element name="{./@new}"/>
)。
我用过你的映射表,但只是为了重命名,添加或删除元素我直接实现了模板;此外,我刚刚使用了映射表的变量而不是顶级元素,因为document('')
在我看来,使用 XSLT 1 中更需要的技术读取样式表。
生成的 XSLT 3 是
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:math="http://www.w3.org/2005/xpath-functions/math"
xmlns:map="http://www.w3.org/2005/xpath-functions/map"
xmlns:array="http://www.w3.org/2005/xpath-functions/array"
exclude-result-prefixes="xs math map array"
version="3.0">
<xsl:param name="rename-map">
<element rename="true" curName="Entry_Number" new="EntryNumber"/>
<element rename="true" curName="Traffic_File" new="TrafficFile"/>
<element rename="true" curName="Status_Code" new="StatusCode"/>
<element rename="true" curName="Header_Country_of_Origin" new="CountryOriginCode"/>
<element rename="true" curName="Importer_or_Owner" new="ImporterOrOwner"/>
<element rename="true" curName="Entry_Total_Additions_to_Value" new="TotalAdditions"/>
<element rename="true" curName="Entry_IRS_Excise_Tax" new="IRS_ExciseTax"/>
<element rename="true" curName="Entry_AD_Duties" new="AD_Duties"/>
<element rename="true" curName="Entry_CV_Duties" new="CV_Duties"/>
<element rename="true" curName="Header_Parties" new="HeaderParties"/>
<element rename="true" curName="Header_Party" new="HeaderParty"/>
<element rename="true" curName="Header_Party_Type" new="CBP_PartyType"/>
<element rename="true" curName="Invoice_Lines" new="InvoiceLines"/>
<element rename="true" curName="Invoice_Line" new="InvoiceLine"/>
<element rename="true" curName="Invoice_Order" new="InvoiceOrder"/>
<element rename="true" curName="Line_Quantity" new="LineQuantity"/>
<element rename="true" curName="Entry_Lines" new="EntryLines"/>
<element rename="true" curName="Entry_Line" new="EntryLine"/>
<element rename="true" curName="CBP7501_Line" new="CBP7501Line"/>
</xsl:param>
<xsl:key name="map-ref" match="element[@rename = 'true']" use="@curName"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="Line_Order"/>
<xsl:template match="Status_Code">
<xsl:next-match/>
<SentSequence>1</SentSequence>
</xsl:template>
<xsl:template match="*[key('map-ref', local-name(), $rename-map)]">
<xsl:element name="{key('map-ref', local-name(), $rename-map)/@new}">
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
在https://xsltfiddle.liberty-development.net/bFukv8t在线,如果您的目标是 XSLT 2 处理器,请将xsl:mode
上面使用的指令替换为身份转换模板
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
如果您还想从该映射数据中进行添加和删除,您可以使用
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="3.0">
<xsl:param name="rename-map">
<element rename="true" curName="Entry_Number" new="EntryNumber"/>
<element rename="true" curName="Traffic_File" new="TrafficFile"/>
<element rename="true" curName="Status_Code" new="StatusCode"/>
<element add="true" curName="Status_Code" new="SentSequence"/>
<element rename="true" curName="Header_Country_of_Origin" new="CountryOriginCode"/>
<element rename="true" curName="Importer_or_Owner" new="ImporterOrOwner"/>
<element rename="true" curName="Entry_Total_Additions_to_Value" new="TotalAdditions"/>
<element rename="true" curName="Entry_IRS_Excise_Tax" new="IRS_ExciseTax"/>
<element rename="true" curName="Entry_AD_Duties" new="AD_Duties"/>
<element rename="true" curName="Entry_CV_Duties" new="CV_Duties"/>
<element rename="true" curName="Header_Parties" new="HeaderParties"/>
<element rename="true" curName="Header_Party" new="HeaderParty"/>
<element rename="true" curName="Header_Party_Type" new="CBP_PartyType"/>
<element rename="true" curName="Invoice_Lines" new="InvoiceLines"/>
<element rename="true" curName="Invoice_Line" new="InvoiceLine"/>
<element rename="true" curName="Invoice_Order" new="InvoiceOrder"/>
<element rename="true" curName="Line_Order" new=""/>
<element rename="true" curName="Line_Quantity" new="LineQuantity"/>
<element rename="true" curName="Entry_Lines" new="EntryLines"/>
<element rename="true" curName="Entry_Line" new="EntryLine"/>
<element rename="true" curName="CBP7501_Line" new="CBP7501Line"/>
</xsl:param>
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:key name="map-ref" match="element[@rename = 'true']" use="@curName"/>
<xsl:key name="new-ref" match="element[@add = 'true']" use="@curName"/>
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="*[key('map-ref', local-name(), $rename-map)[@new = '']]" priority="5"/>
<xsl:template match="Status_Code">
<xsl:next-match/>
<SentSequence>1</SentSequence>
</xsl:template>
<xsl:template match="*[key('map-ref', local-name(), $rename-map)]">
<xsl:element name="{key('map-ref', local-name(), $rename-map)/@new}">
<xsl:apply-templates/>
</xsl:element>
<xsl:apply-templates select=".[key('new-ref', local-name(), $rename-map)]" mode="new"/>
</xsl:template>
<xsl:template match="*" mode="new">
<xsl:element name="{key('new-ref', local-name(), $rename-map)/@new}">1</xsl:element>
</xsl:template>
</xsl:stylesheet>
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句