XSLT 3.0 增量合并

XSLT 3.0 incremental merge

我有两个 XSLT 工作流程:完整 (XSLT2)增量 (XSLT3)

下面full3.xmlFull工作流的合并拆分结果:

<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 工作流的预期结果应该是:

    <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>

就目前的情况而言,我对 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 元素或用于合并合同的代码。我不知道那是因为您对这段代码没有任何问题,还是因为您不知道如何编写它。