问题描述
我遇到以下情况:
我正在使用第三方xsl模板系统(kosit XRechnung),该系统允许通过指定自己的.xsl文件作为处理入口点来配置自定义适应。
流程如下:
+--------+
| |
| |
| |
| in.xml |
| |
+--------+
|
|
|
V
+--------+
| |
| | import +--------+
| my.xsl | <-------- | |
| | | adapt | import +---------+
| | | .xsl | <-------| |
+--------+ | | | default |
| | | | .xsl |
-| +--------+ | |
| | |
V +---------+
+--------+
| |
| |
| out |
| .xml |
| |
+--------+
my.xsl
是由我提供的一些.xml数据提供的处理入口点
adapt.xsl
是一种改编,提供了一个命名模板,该模板有时被
调用
default.xsl
会做很多事情来创建最终的输出XML文档。
default.xsl:
<!-- ... -->
<xsl:when test="s:scenario">
<rep:scenarioMatched>
<xsl:apply-templates select="s:scenario" mode="copy" />
<xsl:call-template name="documentData" />
<xsl:sequence select="$validationStepResults" />
</rep:scenarioMatched>
</xsl:when>
<!-- ... -->
adapt.xsl:
<!-- Overwritten (default.xsl) -->
<xsl:template name="documentData">
<rep:documentData>
<xsl:for-each select="
$input-document/*/cac:AccountingsupplierParty/cac:Party/cac:PartyLegalEntity/cbc:RegistrationName,$input-document/rsm:CrossIndustryInvoice/rsm:SupplyChainTradeTransaction/ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:Name">
<seller>
<xsl:value-of select="."/>
</seller>
</xsl:for-each>
<xsl:for-each select="
$input-document/*/cbc:ID,$input-document/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:ID">
<id>
<xsl:value-of select="."/>
</id>
</xsl:for-each>
<xsl:for-each select="$input-document/*/cbc:IssueDate,$input-document/rsm:CrossIndustryInvoice/rsm:ExchangedDocument/ram:IssueDateTime/udt:DateTimeString">
<issueDate>
<xsl:value-of select="."/>
</issueDate>
</xsl:for-each>
</rep:documentData>
</xsl:template>
现在在我的顶级.xsl中,我可以再次覆盖在default.xsl
中调用的命名模板:
my.xsl:
<?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:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rep="http://www.xoev.de/de/validator/varl/1"
xmlns:s="http://www.xoev.de/de/validator/framework/1/scenarios"
xmlns:in="http://www.xoev.de/de/validator/framework/1/createreportinput"
xmlns:svrl="http://purl.oclc.org/dsdl/svrl"
xmlns:xd="http://www.oxygenxml.com/ns/doc/xsl"
xmlns:html="http://www.w3.org/1999/xhtml"
xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100"
xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessinformationEntity:100"
xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100"
xmlns:myns="urn:mycompany:xrechnung:data:enhancements"
exclude-result-prefixes="xs"
version="2.0">
<xsl:import href="./adapt.xsl"/>
<xsl:output method="xml" indent="yes"/>
<!-- Overwritten (default.xsl) -->
<xsl:template name="documentData">
<rep:documentData>
<myns:MyContainer>
<myns:MyElement>
<!-- Enhanced stuff -->
</myns:MyElement>
</myns:MyContainer>
<!-- xsl:call-template name="documentData"/-->
</rep:documentData>
</xsl:template>
</xsl:stylesheet>
问题是:
如何在不复制adapt.xsl
命名模板的xsl代码的情况下应用documentData
中定义的内容(而不更改default.xsl
或adapt.xsl
)?
解决方法
在XSLT 3软件包的上下文中,这是可能的,请参见https://www.w3.org/TR/xslt-30/#refer-to-overridden:
在一个命名模板中,该模板显示为xsl:override的子代,名称为
xsl:original
可能显示为的名称属性的值 xsl:call-template:例如<xsl:call-template name="xsl:original"/>
。
Saxon 9.8和更高版本支持带有软件包的XSLT 3。
对于具体示例,我认为您需要使用第四个文件(例如adapt-package-wrapper.xsl
),该文件是导入adapt.xsl
的命名包,例如
<xsl:package xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0"
name="http://example.com/adapt1" package-version="1.0">
<xsl:expose component="template" names="documentData" visibility="public"/>
<xsl:import href="adapt.xsl"/>
</xsl:package>
然后在my.xsl
中,您需要声明覆盖:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0">
<xsl:use-package name="http://example.com/adapt1" version="1.0">
<xsl:override>
<xsl:template name="documentData">
<rep:documentData>
<myns:MyContainer>
<myns:MyElement>
<!-- Enhanced stuff -->
</myns:MyElement>
</myns:MyContainer>
<!-- xsl:call-template name="documentData"/-->
<xsl:call-template name="xsl:original"/>
</rep:documentData>
</xsl:template>
</xsl:override>
</xsl:use-package>
...
</xsl:stylesheet>
然后,主要问题是让Saxon知道如何在命令行上使用以下方式将软件包名称http://example.com/adapt1
映射到软件包文件: -lib:adapt-package-wrapper.xsl
。或者,您可以使用配置文件。不确定是否可以在您的环境中做到这一点。