使用 XSLT 根据给定的数字对 XML 文件进行分组
Group XML file based on a given number using XSLT
我想根据 XML 标签值对 XML 文件进行分组。下面是我的输入 XML.
<Root>
<GroupNumber>3</GroupNumber>
<EDICustomer>
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
</EDICustomer>
</Root>
我不知道那里会有多少个 EDICustomerLine 标签。如果 GroupNumber 值大于 EDICustomerLine 标签的数量,则保留 EDICustomer 子标签,但如果 GroupNumber 小于 EDICustomerLine 标签,我们必须根据 GroupNumber 标签值拆分 EDICustomerLine 标签。所以在这种情况下,预期的 XML 将如下所示。
<Root>
<EDICustomer>
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
</EDICustomer>
<EDICustomer>
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
</EDICustomer>
</Root>
第一个 EDICustomer 父标签包含 Company、Customer、CreationDate、CreationTime 和基于组编号值的 3。就像第二个 EDICustomer 应该包含 3 个或更少的标签。我们不知道那里会有多少 EDICustomerLine 标签和 Group Number 的值。还有
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
以上部分应在所有 EDICustomer 组中重复(如果我们找到一种基于组号循环 EDICustomerLine 的方法,这部分将成为可能)。
首先我想知道这种情况在XSLT中是否可行。
如果可以的话,你们能帮帮我吗?
您可以使用以下 XSLT-2.0 样式表获得所需的结果。它将 <EDICustomerLine>
元素分组为 GroupNumber
组,然后遍历 current-group()
。常量部分由第一个 xsl:copy-of
.
创建
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="text()" />
<!-- identity template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="Root">
<xsl:variable name="max" select="GroupNumber" />
<xsl:copy>
<!-- Handle the "zero-items" situation" -->
<xsl:if test="count(EDICustomer/EDICustomerLine) = 0">
<EDICustomer>
<xsl:copy-of select="EDICustomer[1]/Company | EDICustomer[1]/Customer | EDICustomer[1]/CreationDate | EDICustomer[1]/CreationTime" />
</EDICustomer>
</xsl:if>
<xsl:for-each-group select="EDICustomer/EDICustomerLine" group-by="(position()-1) idiv $max">
<EDICustomer>
<!-- Add a <GroupNr> element with the index of the group -->
<GroupNr><xsl:value-of select="position()" /></GroupNr>
<xsl:copy-of select="../Company | ../Customer | ../CreationDate | ../CreationTime" />
<xsl:copy-of select="current-group()" />
</EDICustomer>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
其结果是:
<Root>
<EDICustomer>
<GroupNr>1</GroupNr>
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
</EDICustomer>
<EDICustomer>
<GroupNr>2</GroupNr>
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
</EDICustomer>
</Root>
如愿以偿。
我想根据 XML 标签值对 XML 文件进行分组。下面是我的输入 XML.
<Root>
<GroupNumber>3</GroupNumber>
<EDICustomer>
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
</EDICustomer>
</Root>
我不知道那里会有多少个 EDICustomerLine 标签。如果 GroupNumber 值大于 EDICustomerLine 标签的数量,则保留 EDICustomer 子标签,但如果 GroupNumber 小于 EDICustomerLine 标签,我们必须根据 GroupNumber 标签值拆分 EDICustomerLine 标签。所以在这种情况下,预期的 XML 将如下所示。
<Root>
<EDICustomer>
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
</EDICustomer>
<EDICustomer>
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
</EDICustomer>
</Root>
第一个 EDICustomer 父标签包含 Company、Customer、CreationDate、CreationTime 和基于组编号值的 3。就像第二个 EDICustomer 应该包含 3 个或更少的标签。我们不知道那里会有多少 EDICustomerLine 标签和 Group Number 的值。还有
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
以上部分应在所有 EDICustomer 组中重复(如果我们找到一种基于组号循环 EDICustomerLine 的方法,这部分将成为可能)。
首先我想知道这种情况在XSLT中是否可行。
如果可以的话,你们能帮帮我吗?
您可以使用以下 XSLT-2.0 样式表获得所需的结果。它将 <EDICustomerLine>
元素分组为 GroupNumber
组,然后遍历 current-group()
。常量部分由第一个 xsl:copy-of
.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="text()" />
<!-- identity template -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*" />
</xsl:copy>
</xsl:template>
<xsl:template match="Root">
<xsl:variable name="max" select="GroupNumber" />
<xsl:copy>
<!-- Handle the "zero-items" situation" -->
<xsl:if test="count(EDICustomer/EDICustomerLine) = 0">
<EDICustomer>
<xsl:copy-of select="EDICustomer[1]/Company | EDICustomer[1]/Customer | EDICustomer[1]/CreationDate | EDICustomer[1]/CreationTime" />
</EDICustomer>
</xsl:if>
<xsl:for-each-group select="EDICustomer/EDICustomerLine" group-by="(position()-1) idiv $max">
<EDICustomer>
<!-- Add a <GroupNr> element with the index of the group -->
<GroupNr><xsl:value-of select="position()" /></GroupNr>
<xsl:copy-of select="../Company | ../Customer | ../CreationDate | ../CreationTime" />
<xsl:copy-of select="current-group()" />
</EDICustomer>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
其结果是:
<Root>
<EDICustomer>
<GroupNr>1</GroupNr>
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
</EDICustomer>
<EDICustomer>
<GroupNr>2</GroupNr>
<Company>IWS</Company>
<Customer>150</Customer>
<CreationDate>2020-03-15T10:29:08.813</CreationDate>
<CreationTime>2020-03-15T10:29:08.813</CreationTime>
<EDICustomerLine>
<Barcode>447896130245</Barcode>
<ItemDescription>Medium</ItemDescription>
<Warehouse>B01</Warehouse>
<Status>12</Status>
</EDICustomerLine>
</EDICustomer>
</Root>
如愿以偿。