XSLT 将具有相同 ID 的行项目组合到单独的记录中

Posted

技术标签:

【中文标题】XSLT 将具有相同 ID 的行项目组合到单独的记录中【英文标题】:XSLT to combine Line Items with same ID into separate records 【发布时间】:2021-08-17 00:06:33 【问题描述】:

尝试使用 XSLT 在一个“记录”下动态组合/分组具有相同“invoice_id”值的行项目(标题、行、费用)。

在输入的 XML 中,有 Header、Line、Charge 等多个项的出现次数是无限的。

在输出 XML 中,我们尝试将发票 ID 相同的 Header、Line 和 Charges 分组到一个父节点“Record”下。父节点“记录”重复的次数与输入 XML 中的发票 ID 一样多。

请在下面找到输入和预期输出:

输入 XML 下面提供了输入 XML:

    <?xml version="1.0" encoding="utf-8"?>
    <ns:MT_OkayToPay_Source xmlns:ns="http://kpmg.com/xi/Coupa/OkayToPay">
        <Header>
            <type>Header</type>
            <invoice_id>5</invoice_id>
        </Header>
        <Header>
            <type>Header</type>
            <invoice_id>6</invoice_id>
        </Header>
        <Line>
            <type>Line</type>
            <invoice_id>5</invoice_id>
        </Line>
        <Line>
            <type>Line</type>
            <invoice_id>6</invoice_id>
        </Line>
        <Charge>
            <type>Charge</type>
            <invoice_id>5</invoice_id>
            <invoice_charge_invoice_id>10</invoice_charge_invoice_id>
        </Charge>
        <Charge>
            <type>Charge</type>
            <invoice_id>5</invoice_id>
            <invoice_charge_invoice_id>11</invoice_charge_invoice_id>
        </Charge>
        <Charge>
            <type>Charge</type>
            <invoice_id>6</invoice_id>
            <invoice_charge_invoice_id>13</invoice_charge_invoice_id>
        </Charge>
        <Charge>
            <type>Charge</type>
            <invoice_id>6</invoice_id>
            <invoice_charge_invoice_id>14</invoice_charge_invoice_id>
        </Charge>
</ns:MT_OkayToPay_Source>

输出 XML 预期输出如下

<?xml version="1.0" encoding="utf-8"?>
<ns:MT_OkayToPay_Source xmlns:ns="http://kpmg.com/xi/Coupa/OkayToPay">
    <Record>
    <Header>
        <type>Header</type>
        <invoice_id>5</invoice_id>
    </Header>
    <Line>
        <type>Line</type>
        <invoice_id>5</invoice_id>
   </Line>
    <Charge>
        <type>Charge</type>
        <invoice_id>5</invoice_id>
        <invoice_charge_invoice_id>10</invoice_charge_invoice_id>
    </Charge>
    <Charge>
        <type>Charge</type>
        <invoice_id>5</invoice_id>
        <invoice_charge_invoice_id>11</invoice_charge_invoice_id>   
    </Charge>
    </Record>
    <Record>
    <Header>
        <type>Header</type>
        <invoice_id>6</invoice_id>
    </Header>
    <Line>
        <type>Line</type>
        <invoice_id>6</invoice_id>  
    </Line>
    <Charge>
        <type>Charge</type>
        <invoice_id>6</invoice_id>
        <invoice_charge_invoice_id>13</invoice_charge_invoice_id>   
    </Charge>
    <Charge>
        <type>Charge</type>
        <invoice_id>6</invoice_id>
        <invoice_charge_invoice_id>14</invoice_charge_invoice_id>   
    </Charge>
 </Record>
</ns:MT_OkayToPay_Source>

请帮忙。

【问题讨论】:

请就您在尝试完成此操作时遇到的困难提出一个具体问题。否则看起来你只是在找人为你编写代码。---你可以在这里找到几个起点:***.com/tags/xslt-grouping/info 顺便说一句,如果每张发票都有一个 Header 和一个不同的 invoice_id,那么这是一个小问题:只需为每个 Header 创建一个 Record 并使用key. 【参考方案1】:

找到答案:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:template match="/*">
     <root>
      <xsl:for-each-group select="*" group-by="invoice_id">
       <record>
        <xsl:copy-of select="current-group()"/>
       </record>
      </xsl:for-each-group>
 
      
     </root>
 
 </xsl:template>

</xsl:stylesheet>

要在 XSLT 1.0 中达到同样的效果,请使用以下命令:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:key name="Records_by_invoice_id" match="*" use="invoice_id"/>

<xsl:template match="/*">
  <MT_OkayToPay_Source>
   <xsl:apply-templates/>
  </MT_OkayToPay_Source>
 </xsl:template>

<xsl:template match=
   "MT_OkayToPay_Source/*[generate-id()=generate-id(key('Records_by_invoice_id',invoice_id)[1])]">

  <record>
   <xsl:copy-of select="key('Records_by_invoice_id',invoice_id)"/>
  </record>
 </xsl:template>
 
 <xsl:template match=
   "MT_OkayToPay_Source/*[not(generate-id()=generate-id(key('Records_by_invoice_id',invoice_id)[1]))]"/>

  </xsl:stylesheet>

谢谢!

问候

Vishakha Khona

【讨论】:

以上是关于XSLT 将具有相同 ID 的行项目组合到单独的记录中的主要内容,如果未能解决你的问题,请参考以下文章

使用 XSLT 将具有相同 ID 的元素 (XML) 合并到 txt 文件

从具有相同 ID 的行创建列

PHP MySQL将来自不同行的单元格组合在一起具有相同的值

如何将转换后的行汇总并集中到一个具有相同 ID 的字段中?

将 SQL 数据插入具有相同 ID 的行中?

如何合并具有“相同父亲”、相同方法和相同 id=0 的两个节点(使用 XSLT)?