XSLT 3.0 增量合并
XSLT 3.0 incremental merge
我有两个 XSLT 工作流程:完整 (XSLT2) 和 增量 (XSLT3)。
下面full3.xml
是Full
工作流的合并拆分结果:
<Account>
<metadata>
<_uri>full3.xml</_uri>
<created>2020-11-26T23:16:08.076-07:00</created>
<lastModified>2020-11-26T23:16:08.076-07:00</lastModified>
<merge-lineage>
<merged-uri>lot960151-3.xml</merged-uri>
<merged-uri>lot860150-3.xml</merged-uri>
</merge-lineage>
</metadata>
<accountPersistentID>51b10faa</accountPersistentID>
<accountID>ACC300</accountID>
<accountName>bonafide-3</accountName>
<Item>
<contract>
<amount>
<currency>USD</currency>
<amount>5000000.00</amount>
</amount>
</contract>
<contract>
<amount>
<currency>USD</currency>
<amount>4000000.00</amount>
</amount>
</contract>
</Item></Account>
我有后续的增量输入 XML 要匹配并(如果匹配)合并;如果不匹配,则将其转换为上述类似结构。
lot660152-3.xml
是原始文档结构。匹配和合并标准是 accountId
和 accountName
<ContractServicing>
<account id="ACC3">
<accountId>ACC300</accountId>
<accountName>bonafide-3</accountName>
<accountBeneficiary href="party5"/>
<servicingParty href="party6"/>
</account>
<contract>
<amount>
<currency>USD</currency>
<amount>5700000.00</amount>
</amount>
</contract>
<contract>
<amount>
<currency>USD</currency>
<amount>4000000.00</amount>
</amount>
</contract></ContractServicing>
Incremental
XSLT 工作流的预期结果应该是:
lot660152-3.xml
被匹配,其每个contract
应合并到full3.xml
中的Item
元素
(注意:_uri
是在 Full
工作流程中生成的,可以在 incremental
工作流程中更改。但是 accountPersistentID
在 Full
工作流程中生成的应保持不变. 此外 lastModified
和 merged-uri
如果有任何合并事件将被更新。
<Account>
<metadata>
<_uri>full3.xml</_uri>
<created>2020-11-26T23:16:08.076-07:00</created>
<lastModified>2020-11-29T00:00:00.000-00:00</lastModified>
<merge-lineage>
<merged-uri>lot960151-3.xml</merged-uri>
<merged-uri>lot860150-3.xml</merged-uri>
<merged-uri>lot660152-3.xml</merged-uri>
</merge-lineage>
</metadata>
<accountPersistentID>51b10faa</accountPersistentID>
<accountID>ACC300</accountID>
<accountName>bonafide-3</accountName>
<Item>
<contract>
<amount>
<currency>USD</currency>
<amount>5000000.00</amount>
</amount>
</contract>
<contract>
<amount>
<currency>USD</currency>
<amount>4000000.00</amount>
</amount>
</contract>
<contract>
<amount>
<currency>USD</currency>
<amount>5700000.00</amount>
</amount>
</contract>
<contract>
<amount>
<currency>USD</currency>
<amount>4000000.00</amount>
</amount>
</contract>
</Item>
</Account>
Incremental
工作流应为不匹配的原始文档创建类似于 full3.xml
的新文档。
就目前的情况而言,我对 Full
工作流程感到满意,但在 Incremental
工作流程期间,我似乎无法在 XSLT3 merge
指令中找到任何一行。
My XSLT Incremental
workflow
<xsl:template match="/">
<xsl:merge>
<xsl:merge-source name="full" streamable="yes" for-each-source="$full-docs" select="Account">
<xsl:merge-key select="accountID"/>
</xsl:merge-source>
<xsl:merge-source name="incremental" for-each-source="$incre-docs" select="ContractServicing">
<xsl:merge-key select="account/accountId"/>
</xsl:merge-source>
<xsl:merge-action>
<xsl:choose>
<xsl:when test="current-merge-group('incremental')/account/accountId = current-merge-group('full')/accountID">
<xsl:apply-templates select="current-merge-group('full')"/>
<xsl:for-each select="current-merge-group('full')/Item">
<xsl:copy-of select="current-merge-group('incremental')/contract"/>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-merge-group('incremental')" />
</xsl:otherwise>
</xsl:choose>
</xsl:merge-action>
</xsl:merge>
</xsl:template>
结果是匹配的增量contract
的none合并为Item
,不匹配的文档没有被转换。 (已由 Michael Kay 解决)
Null Pointer
我添加了一些样板:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
expand-text="yes"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:mode name="merge-contracts" on-no-match="shallow-copy"/>
<xsl:mode name="unmatched" on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
然后将 xsl:merge-action
更改为
<xsl:merge-action>
<xsl:choose>
<xsl:when test="current-merge-group('incremental')/account/accountId = current-merge-group('full')/accountID">
<xsl:apply-templates select="current-merge-group('full')" mode="merge-contracts">
<xsl:with-param name="extra" select="current-merge-group('incremental')"
tunnel="yes" as="element(ContractServicing)"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-merge-group('incremental')" mode="unmatched"/>
</xsl:otherwise>
</xsl:choose>
</xsl:merge-action>
因此,如果匹配,它会在合并合同模式下处理主文档,并在隧道参数中传递增量文档;如果没有匹配,它会以“不匹配”模式处理增量文档。
merged-contracts
模式有三个模板规则:
<xsl:template match="lastModified/text()" mode="merge-contracts">
<xsl:value-of select="current-dateTime()"/>
</xsl:template>
<xsl:template match="merge-lineage" mode="merge-contracts">
<xsl:param name="extra" tunnel="yes" as="element(ContractServicing)"/>
<xsl:copy>
<xsl:copy-of select="*"/>
<merged-uri>{
tokenize($extra/root()/document-uri(),'/')[last()]
}</merged-uri>
</xsl:copy>
</xsl:template>
<xsl:template match="Item" mode="merge-contracts">
<xsl:param name="extra" tunnel="yes" as="element(ContractServicing)"/>
<xsl:copy>
<xsl:copy-of select="*, $extra//contract"/>
</xsl:copy>
</xsl:template>
这可能不会做您想做的所有事情,但我认为它抓住了本质。
在增量文档不匹配的地方,它变成了一个非常常规的转换,我近似为:
<xsl:template match="ContractServicing" mode="unmatched">
<xsl:result-document href="unmatched.xml">
<Account>
<metadata>...</metadata>
<accountPersistentID>...</accountPersistentID>
<xsl:copy-of select="//contract"/>
</Account>
</xsl:result-document>
</xsl:template>
我不太确定您的问题出在哪里。您的代码引用了一个不存在的“item”元素;而且您没有向我们展示任何用于组合 merge-lineage 元素或用于合并合同的代码。我不知道那是因为您对这段代码没有任何问题,还是因为您不知道如何编写它。
我有两个 XSLT 工作流程:完整 (XSLT2) 和 增量 (XSLT3)。
下面full3.xml
是Full
工作流的合并拆分结果:
<Account>
<metadata>
<_uri>full3.xml</_uri>
<created>2020-11-26T23:16:08.076-07:00</created>
<lastModified>2020-11-26T23:16:08.076-07:00</lastModified>
<merge-lineage>
<merged-uri>lot960151-3.xml</merged-uri>
<merged-uri>lot860150-3.xml</merged-uri>
</merge-lineage>
</metadata>
<accountPersistentID>51b10faa</accountPersistentID>
<accountID>ACC300</accountID>
<accountName>bonafide-3</accountName>
<Item>
<contract>
<amount>
<currency>USD</currency>
<amount>5000000.00</amount>
</amount>
</contract>
<contract>
<amount>
<currency>USD</currency>
<amount>4000000.00</amount>
</amount>
</contract>
</Item></Account>
我有后续的增量输入 XML 要匹配并(如果匹配)合并;如果不匹配,则将其转换为上述类似结构。
lot660152-3.xml
是原始文档结构。匹配和合并标准是 accountId
和 accountName
<ContractServicing>
<account id="ACC3">
<accountId>ACC300</accountId>
<accountName>bonafide-3</accountName>
<accountBeneficiary href="party5"/>
<servicingParty href="party6"/>
</account>
<contract>
<amount>
<currency>USD</currency>
<amount>5700000.00</amount>
</amount>
</contract>
<contract>
<amount>
<currency>USD</currency>
<amount>4000000.00</amount>
</amount>
</contract></ContractServicing>
Incremental
XSLT 工作流的预期结果应该是:
lot660152-3.xml
被匹配,其每个contract
应合并到full3.xml
中的Item
元素 (注意:_uri
是在Full
工作流程中生成的,可以在incremental
工作流程中更改。但是accountPersistentID
在Full
工作流程中生成的应保持不变. 此外lastModified
和merged-uri
如果有任何合并事件将被更新。
<Account>
<metadata>
<_uri>full3.xml</_uri>
<created>2020-11-26T23:16:08.076-07:00</created>
<lastModified>2020-11-29T00:00:00.000-00:00</lastModified>
<merge-lineage>
<merged-uri>lot960151-3.xml</merged-uri>
<merged-uri>lot860150-3.xml</merged-uri>
<merged-uri>lot660152-3.xml</merged-uri>
</merge-lineage>
</metadata>
<accountPersistentID>51b10faa</accountPersistentID>
<accountID>ACC300</accountID>
<accountName>bonafide-3</accountName>
<Item>
<contract>
<amount>
<currency>USD</currency>
<amount>5000000.00</amount>
</amount>
</contract>
<contract>
<amount>
<currency>USD</currency>
<amount>4000000.00</amount>
</amount>
</contract>
<contract>
<amount>
<currency>USD</currency>
<amount>5700000.00</amount>
</amount>
</contract>
<contract>
<amount>
<currency>USD</currency>
<amount>4000000.00</amount>
</amount>
</contract>
</Item>
</Account>
Incremental
工作流应为不匹配的原始文档创建类似于full3.xml
的新文档。
就目前的情况而言,我对 Full
工作流程感到满意,但在 Incremental
工作流程期间,我似乎无法在 XSLT3 merge
指令中找到任何一行。
My XSLT
Incremental
workflow
<xsl:template match="/">
<xsl:merge>
<xsl:merge-source name="full" streamable="yes" for-each-source="$full-docs" select="Account">
<xsl:merge-key select="accountID"/>
</xsl:merge-source>
<xsl:merge-source name="incremental" for-each-source="$incre-docs" select="ContractServicing">
<xsl:merge-key select="account/accountId"/>
</xsl:merge-source>
<xsl:merge-action>
<xsl:choose>
<xsl:when test="current-merge-group('incremental')/account/accountId = current-merge-group('full')/accountID">
<xsl:apply-templates select="current-merge-group('full')"/>
<xsl:for-each select="current-merge-group('full')/Item">
<xsl:copy-of select="current-merge-group('incremental')/contract"/>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-merge-group('incremental')" />
</xsl:otherwise>
</xsl:choose>
</xsl:merge-action>
</xsl:merge>
</xsl:template>
结果是匹配的增量contract
的none合并为Item
,不匹配的文档没有被转换。 (已由 Michael Kay 解决)
Null Pointer
我添加了一些样板:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
expand-text="yes"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:mode name="merge-contracts" on-no-match="shallow-copy"/>
<xsl:mode name="unmatched" on-no-match="shallow-copy"/>
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
然后将 xsl:merge-action
更改为
<xsl:merge-action>
<xsl:choose>
<xsl:when test="current-merge-group('incremental')/account/accountId = current-merge-group('full')/accountID">
<xsl:apply-templates select="current-merge-group('full')" mode="merge-contracts">
<xsl:with-param name="extra" select="current-merge-group('incremental')"
tunnel="yes" as="element(ContractServicing)"/>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-merge-group('incremental')" mode="unmatched"/>
</xsl:otherwise>
</xsl:choose>
</xsl:merge-action>
因此,如果匹配,它会在合并合同模式下处理主文档,并在隧道参数中传递增量文档;如果没有匹配,它会以“不匹配”模式处理增量文档。
merged-contracts
模式有三个模板规则:
<xsl:template match="lastModified/text()" mode="merge-contracts">
<xsl:value-of select="current-dateTime()"/>
</xsl:template>
<xsl:template match="merge-lineage" mode="merge-contracts">
<xsl:param name="extra" tunnel="yes" as="element(ContractServicing)"/>
<xsl:copy>
<xsl:copy-of select="*"/>
<merged-uri>{
tokenize($extra/root()/document-uri(),'/')[last()]
}</merged-uri>
</xsl:copy>
</xsl:template>
<xsl:template match="Item" mode="merge-contracts">
<xsl:param name="extra" tunnel="yes" as="element(ContractServicing)"/>
<xsl:copy>
<xsl:copy-of select="*, $extra//contract"/>
</xsl:copy>
</xsl:template>
这可能不会做您想做的所有事情,但我认为它抓住了本质。
在增量文档不匹配的地方,它变成了一个非常常规的转换,我近似为:
<xsl:template match="ContractServicing" mode="unmatched">
<xsl:result-document href="unmatched.xml">
<Account>
<metadata>...</metadata>
<accountPersistentID>...</accountPersistentID>
<xsl:copy-of select="//contract"/>
</Account>
</xsl:result-document>
</xsl:template>
我不太确定您的问题出在哪里。您的代码引用了一个不存在的“item”元素;而且您没有向我们展示任何用于组合 merge-lineage 元素或用于合并合同的代码。我不知道那是因为您对这段代码没有任何问题,还是因为您不知道如何编写它。