XSLT 2.0 - 基于条件对节点进行分组和复制 - 错误

XSLT 2.0 - Group and copy nodes based on condition - Error

提问人:MAT0718 提问时间:11/5/2023 最后编辑:MAT0718 更新时间:11/5/2023 访问量:57

问:

这是我的源 XML

<?xml version="1.0" encoding="UTF-8"?>
<Workers>
    <Worker>
        <UniqueID>67896</UniqueID>
        <ExpenseAmount>400.00</ExpenseAmount>
        <BonusAmount>230.00</BonusAmount>
    </Worker>
    <Worker>
        <UniqueID>678965</UniqueID>
        <ExpenseAmount>400.00</ExpenseAmount>
        <BonusAmount>230.00</BonusAmount>
    </Worker>
    <Worker>
        <UniqueID>12354</UniqueID>
        <ExpenseAmount>998.00</ExpenseAmount>        
        <Misc>
            <Date>2023-10-10-07:00</Date>
            <BonusAmount>400.00</BonusAmount>
        </Misc>
        <Misc>
            <Date>2023-10-09-07:00</Date>
            <BonusAmount>900.00</BonusAmount>
        </Misc>
    </Worker>
    <Worker>
        <UniqueID>4567</UniqueID>
        <ExpenseAmount>1507.00</ExpenseAmount>        
        <Misc>
            <Date>2023-10-06-07:00</Date>
            <BonusAmount>322.00</BonusAmount>
        </Misc>
        <Misc>
            <Date>2023-10-08-07:00</Date>
            <BonusAmount>800.00</BonusAmount>
        </Misc>
        <Misc>
            <Date>2023-10-09-07:00</Date>
            <BonusAmount>410.00</BonusAmount>
        </Misc>
    </Worker>
</Workers>

这是我想做的。

  • 整个文档中有 4 个不同的日期,例如 和2023-10-10-07:002023-10-09-07:002023-10-06-07:00 2023-10-08-07:00
  • 由于我的最终输出应该基于和 4 个不同的 日期在我的源 XML 上,我的预期结果应该有 4 个节点,每个节点都包含对应于<Date><Records><Date><Worker>
  • 但是,有 2 个节点没有任何元素,因此任何没有的节点都应复制到所有节点下<Worker><Date><Worker><Date><Records>

我当前的 XSLT。感谢 michael.hor257k

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

    <xsl:template match="/Workers">
        <Workers>
            <xsl:variable name="undated" select="Worker[not(Misc)]"/>
            <xsl:variable name="dated" select="Worker[(Misc)]"/>

            <xsl:for-each-group select="Worker/Misc" group-by="Date">
                <Records>
                    <xsl:copy-of select="$undated"/>
                    <xsl:copy-of select="current-group()"/>
                </Records>
            </xsl:for-each-group>
        </Workers>
    </xsl:template>
</xsl:stylesheet>

我目前的结果

<?xml version="1.0" encoding="UTF-8"?>
<Workers>
   <Records>
      <Worker>
         <UniqueID>67896</UniqueID>
         <ExpenseAmount>400.00</ExpenseAmount>
         <BonusAmount>230.00</BonusAmount>
      </Worker>
      <Worker>
         <UniqueID>678965</UniqueID>
         <ExpenseAmount>400.00</ExpenseAmount>
         <BonusAmount>230.00</BonusAmount>
      </Worker>
      <Misc>
         <Date>2023-10-10-07:00</Date>
         <BonusAmount>400.00</BonusAmount>
      </Misc>
   </Records>
   <Records>
      <Worker>
         <UniqueID>67896</UniqueID>
         <ExpenseAmount>400.00</ExpenseAmount>
         <BonusAmount>230.00</BonusAmount>
      </Worker>
      <Worker>
         <UniqueID>678965</UniqueID>
         <ExpenseAmount>400.00</ExpenseAmount>
         <BonusAmount>230.00</BonusAmount>
      </Worker>
      <Misc>
         <Date>2023-10-09-07:00</Date>
         <BonusAmount>900.00</BonusAmount>
      </Misc>
      <Misc>
         <Date>2023-10-09-07:00</Date>
         <BonusAmount>410.00</BonusAmount>
      </Misc>
   </Records>
   <Records>
      <Worker>
         <UniqueID>67896</UniqueID>
         <ExpenseAmount>400.00</ExpenseAmount>
         <BonusAmount>230.00</BonusAmount>
      </Worker>
      <Worker>
         <UniqueID>678965</UniqueID>
         <ExpenseAmount>400.00</ExpenseAmount>
         <BonusAmount>230.00</BonusAmount>
      </Worker>
      <Misc>
         <Date>2023-10-06-07:00</Date>
         <BonusAmount>322.00</BonusAmount>
      </Misc>
   </Records>
   <Records>
      <Worker>
         <UniqueID>67896</UniqueID>
         <ExpenseAmount>400.00</ExpenseAmount>
         <BonusAmount>230.00</BonusAmount>
      </Worker>
      <Worker>
         <UniqueID>678965</UniqueID>
         <ExpenseAmount>400.00</ExpenseAmount>
         <BonusAmount>230.00</BonusAmount>
      </Worker>
      <Misc>
         <Date>2023-10-08-07:00</Date>
         <BonusAmount>800.00</BonusAmount>
      </Misc>
   </Records>
</Workers>

我当前的输出有 4 个节点,但 --> 没有如下所示的父节点,这是不正确的。<Records><Misc><Date><Worker>

<?xml version="1.0" encoding="UTF-8"?>
<Workers>
    <Records>
        <Worker>
            <UniqueID>67896</UniqueID>
            <ExpenseAmount>400.00</ExpenseAmount>
            <BonusAmount>230.00</BonusAmount>
        </Worker>
        <Worker>
            <UniqueID>678965</UniqueID>
            <ExpenseAmount>400.00</ExpenseAmount>
            <BonusAmount>230.00</BonusAmount>
        </Worker>
        <Misc> <!-- Misc should have been under it's <Worker> node -->
            <Date>2023-10-10-07:00</Date>
            <BonusAmount>400.00</BonusAmount>
        </Misc>
    </Records>
</Workers>

预期结果

<?xml version="1.0" encoding="UTF-8"?>
<Workers>
    <Records>
        <Worker>
            <UniqueID>67896</UniqueID>
            <ExpenseAmount>400.00</ExpenseAmount>
            <BonusAmount>230.00</BonusAmount>
        </Worker>
        <Worker>
            <UniqueID>678965</UniqueID>
            <ExpenseAmount>400.00</ExpenseAmount>
            <BonusAmount>230.00</BonusAmount>
        </Worker>
        <Worker>
            <UniqueID>12354</UniqueID>
            <ExpenseAmount>998.00</ExpenseAmount>
            <Misc>
                <Date>2023-10-10-07:00</Date>
                <BonusAmount>400.00</BonusAmount>
            </Misc>
        </Worker>
    </Records>
    <Records>
        <Worker>
            <UniqueID>67896</UniqueID>
            <ExpenseAmount>400.00</ExpenseAmount>
            <BonusAmount>230.00</BonusAmount>
        </Worker>
        <Worker>
            <UniqueID>678965</UniqueID>
            <ExpenseAmount>400.00</ExpenseAmount>
            <BonusAmount>230.00</BonusAmount>
        </Worker>
        <Worker>
            <UniqueID>12354</UniqueID>
            <ExpenseAmount>998.00</ExpenseAmount>

            <Misc>
                <Date>2023-10-09-07:00</Date>
                <BonusAmount>900.00</BonusAmount>
            </Misc>
        </Worker>
        <Worker>
            <UniqueID>4567</UniqueID>
            <ExpenseAmount>1507.00</ExpenseAmount>
            <Misc>
                <Date>2023-10-09-07:00</Date>
                <BonusAmount>410.00</BonusAmount>
            </Misc>
        </Worker>
    </Records>
    <Records>
        <Worker>
            <UniqueID>67896</UniqueID>
            <ExpenseAmount>400.00</ExpenseAmount>
            <BonusAmount>230.00</BonusAmount>
        </Worker>
        <Worker>
            <UniqueID>678965</UniqueID>
            <ExpenseAmount>400.00</ExpenseAmount>
            <BonusAmount>230.00</BonusAmount>
        </Worker>
        <Worker>
            <UniqueID>4567</UniqueID>
            <ExpenseAmount>1507.00</ExpenseAmount>
            <Misc>
                <Date>2023-10-06-07:00</Date>
                <BonusAmount>322.00</BonusAmount>
            </Misc>
        </Worker>
    </Records>
    <Records>
        <Worker>
            <UniqueID>67896</UniqueID>
            <ExpenseAmount>400.00</ExpenseAmount>
            <BonusAmount>230.00</BonusAmount>
        </Worker>
        <Worker>
            <UniqueID>678965</UniqueID>
            <ExpenseAmount>400.00</ExpenseAmount>
            <BonusAmount>230.00</BonusAmount>
        </Worker>
        <Worker>
            <UniqueID>4567</UniqueID>
            <ExpenseAmount>1507.00</ExpenseAmount>
            <Misc>
                <Date>2023-10-08-07:00</Date>
                <BonusAmount>800.00</BonusAmount>
            </Misc>
        </Worker>
    </Records>
</Workers>

你能帮我弄清楚这个问题吗?谢谢!

======================================================
仅编辑
以下部分 应用 XSLT 后的结果 michael.hor257k 提供 根据最初提供的源 XML 获取预期结果。但是,在我的源 XML 上,对于相同但不同的下节点,可能有多个节点,如下所示。
<Misc><Date><BonusAmount><Worker>

**Source Data**

<?xml version="1.0" encoding="UTF-8"?>
<Workers>
    <Worker>
        <UniqueID>67896</UniqueID>
        <ExpenseAmount>400.00</ExpenseAmount>
        <BonusAmount>230.00</BonusAmount>
    </Worker>
    <Worker>
        <UniqueID>678965</UniqueID>
        <ExpenseAmount>400.00</ExpenseAmount>
        <BonusAmount>230.00</BonusAmount>
    </Worker>
    <Worker>
        <UniqueID>12354</UniqueID>
        <ExpenseAmount>998.00</ExpenseAmount>        
        <Misc>
            <Date>2023-10-10-07:00</Date>
            <BonusAmount>400.00</BonusAmount> <!-- Amount is 400 here -->
        </Misc>
        <Misc>
            <Date>2023-10-10-07:00</Date>
            <BonusAmount>600.00</BonusAmount> <!-- Amount is 600 here -->
        </Misc>
    </Worker>
</Workers>

XSLT 产生以下结果

<?xml version="1.0" encoding="UTF-8"?>
<Workers>
   <Records>
      <Worker>
         <UniqueID>67896</UniqueID>
         <ExpenseAmount>400.00</ExpenseAmount>
         <BonusAmount>230.00</BonusAmount>
      </Worker>
      <Worker>
         <UniqueID>678965</UniqueID>
         <ExpenseAmount>400.00</ExpenseAmount>
         <BonusAmount>230.00</BonusAmount>
      </Worker>
      <Worker>
         <UniqueID>12354</UniqueID>
         <ExpenseAmount>998.00</ExpenseAmount>
         <Misc>
            <Date>2023-10-10-07:00</Date>
            <BonusAmount>400.00</BonusAmount>
         </Misc>
      </Worker>
      <Worker>
         <UniqueID>12354</UniqueID>
         <ExpenseAmount>998.00</ExpenseAmount>
         <Misc>
            <Date>2023-10-10-07:00</Date>
            <BonusAmount>600.00</BonusAmount>
         </Misc>
      </Worker>
   </Records>
</Workers>

预期结果如下,两个元素应分组到同一节点下<Misc><Worker>

在获得以下结果时,任何帮助都是值得赞赏的。

<?xml version="1.0" encoding="UTF-8"?>
<Workers>
    <Worker>
        <UniqueID>67896</UniqueID>
        <ExpenseAmount>400.00</ExpenseAmount>
        <BonusAmount>230.00</BonusAmount>
    </Worker>
    <Worker>
        <UniqueID>678965</UniqueID>
        <ExpenseAmount>400.00</ExpenseAmount>
        <BonusAmount>230.00</BonusAmount>
    </Worker>
    <Worker>
        <UniqueID>12354</UniqueID>
        <ExpenseAmount>998.00</ExpenseAmount>
        <Misc>
            <Date>2023-10-10-07:00</Date>
            <BonusAmount>400.00</BonusAmount>
        </Misc>
        <Misc>
            <Date>2023-10-10-07:00</Date>
            <BonusAmount>600.00</BonusAmount>
        </Misc>
    </Worker>
</Workers>

获得预期结果的最终解决方案是

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/Workers">
        <Workers>
            <xsl:variable name="undated" select="Worker[not(Misc)]"/>
            <xsl:for-each-group select="Worker/Misc" group-by="Date">
                <Records>
                    <xsl:copy-of select="$undated"/>
                    <Worker>
                        <xsl:copy-of select="../(UniqueID | ExpenseAmount)"/>
                    </Worker>
                    <xsl:for-each select="current-group()">
                        <xsl:copy-of select="."/>
                    </xsl:for-each>
                </Records>
            </xsl:for-each-group>
        </Workers>
    </xsl:template>
</xsl:stylesheet>
XSLT XSLT-2.0

评论


答:

1赞 michael.hor257k 11/5/2023 #1

试试这种方式:

XSLT 2.0 版

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

<xsl:template match="/Workers">
    <Workers>
        <xsl:variable name="undated" select="Worker[not(Misc)]" />
        <xsl:for-each-group select="Worker/Misc" group-by="Date">
            <Records>
                <xsl:copy-of select="$undated"/>
                <xsl:for-each select="current-group()">
                    <Worker>
                        <xsl:copy-of select="../(UniqueID|ExpenseAmount)"/>
                        <xsl:copy-of select="."/>
                    </Worker>
                </xsl:for-each>
            </Records>
        </xsl:for-each-group>
    </Workers>
</xsl:template>

</xsl:stylesheet>

评论

0赞 MAT0718 11/5/2023
非常感谢michael.hor257k,它接近我所期望的。你的代码没有问题。这适用于我最初提供的源 XML,但我的源 XML 也可以有多个 Date',但具有不同的 .我用源 XML、预期结果和当前结果编辑了原始帖子。Misc' element for a same BonusAmount
0赞 michael.hor257k 11/5/2023
仅当具有相同 Date 的 Misc 元素也具有相同的 UniqueID 和 ExpenseAmount 时,显示的结果才有意义。如果总是如此,那么必要的调整是次要的,您应该能够自己进行。
0赞 MAT0718 11/5/2023
是的,具有相同 Date 的杂项元素将始终具有相同的 UniqueID 和 ExpenseAmount。
0赞 MAT0718 11/5/2023
我得到了我所期望的结果,但有一个小的改变,但由于我的过度思考,我花了一个小时才得到我想要的东西,非常感谢 michael.hor257k。为来这里寻求解决方案的任何其他人发布了解决方案,但我的一个问题是,是复制上述所有元素的唯一方法。我正在尝试一种方法,不专门调用元素,因此尝试复制上面的所有元素,但似乎不起作用。你能给我任何提示,将不胜感激?<xsl:copy-of select="../(UniqueID | ExpenseAmount)"/>Misc<xsl:copy-of select="node()"/>Misc
0赞 michael.hor257k 11/5/2023
您可以使用 .<xsl:copy-of select="../(* except Misc)"/>