我有一个格式不正确的XML文件,其中与单个订单项相关的信息被分成多行信息,我正在尝试与父订单项(ITEM_ID)进行分组。信息是顺序的,因此密钥是ITEM_ID节点,但是我似乎无法创建将项目相关信息(ITEM_ID)分组所需的正确XSL,给定以下XML源(已更新以包含新发现的孙元素) XML源代码:
<LINE_INFO>
<ITEM_ID>some_part_num</ITEM_ID>
<DESC>some_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
<LINE_INFO>
<EXT_DESC>more_description_for_some_part_num</EXT_DESC>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>some_other_part_num</ITEM_ID>
<DESC>some_other_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
<LINE_INFO>
<EXT_DESC>more_description_for_some_other_part_num</EXT_DESC>
</LINE_INFO>
<LINE_INFO>
<LINE_NOTE>This is a note related to some_other_part_num</LINE_NOTE>
</LINE_INFO>
<LINE_INFO>
<ADDTL_NOTE_DETAIL>
<NOTE>This is the grandchild note that sometimes appears in my data</NOTE>
</ADDTL_NOTE_DETAIL>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>yet_another_part_num</ITEM_ID>
<DESC>yet_another_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
...
期望的输出:
<LINE_INFO>
<ITEM_ID>some_part_num</ITEM_ID>
<DESC>some_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
<EXT_DESC>more_description_for_some_part_num</EXT_DESC>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>some_other_part_num</ITEM_ID>
<DESC>some_other_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
<EXT_DESC>more_description_for_some_other_part_num</EXT_DESC>
<LINE_NOTE>This is a note related to some_other_part_num</LINE_NOTE>
<NOTE>This is the grandchild note that sometimes appears in my data</NOTE>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>yet_another_part_num</ITEM_ID>
<DESC>yet_another_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
答案 0 :(得分:2)
此转化:
<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="kFollowing" match="LINE_INFO[not(ITEM_ID)]"
use="generate-id(preceding-sibling::LINE_INFO[ITEM_ID][1])"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="LINE_INFO[ITEM_ID]">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
<xsl:apply-templates select="key('kFollowing', generate-id())/node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="LINE_INFO[not(ITEM_ID)]"/>
</xsl:stylesheet>
应用于提供的XML文档(包装在单个顶部元素中以使其格式良好):
<t>
<LINE_INFO>
<ITEM_ID>some_part_num</ITEM_ID>
<DESC>some_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
<LINE_INFO>
<EXT_DESC>more_description_for_some_part_num</EXT_DESC>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>some_other_part_num</ITEM_ID>
<DESC>some_other_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
<LINE_INFO>
<EXT_DESC>more_description_for_some_other_part_num</EXT_DESC>
</LINE_INFO>
<LINE_INFO>
<LINE_NOTE>This is a note related to some_other_part_num</LINE_NOTE>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>yet_another_part_num</ITEM_ID>
<DESC>yet_another_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
</t>
生成想要的正确结果:
<t>
<LINE_INFO>
<ITEM_ID>some_part_num</ITEM_ID>
<DESC>some_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
<EXT_DESC>more_description_for_some_part_num</EXT_DESC>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>some_other_part_num</ITEM_ID>
<DESC>some_other_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
<EXT_DESC>more_description_for_some_other_part_num</EXT_DESC>
<LINE_NOTE>This is a note related to some_other_part_num</LINE_NOTE>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>yet_another_part_num</ITEM_ID>
<DESC>yet_another_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
</t>
请注意:使用密钥轻松有效地识别没有LINE_INFO
子节点且紧跟ITEM_ID
个节点的所有LINE_INFO
个节点一个ITEM_ID
孩子。
答案 1 :(得分:1)
这是一个经典的分组问题。最好的方法取决于您是否拥有XSLT 2.0,或者必须使用1.0。
如果是2.0,您需要使用<xsl:for-each-group>
:
<table>
<xsl:for-each-group select="LINE_INFO" group-starting-with="LINE_INFO[ITEM_ID]">
select
和group-starting-with
的上述XPath表达式假设上下文节点是LINE_INFO元素的父节点。或者,您可以将//
放在两个表达式的前面,但可能会降低性能。
为每个组输出一行,根据您最近的评论将数据放入表格单元格中:
<tr>
<td><xsl:value-of select="current-group()/ITEM_ID" /></td>
<td>
<xsl:value-of "concat(current-group()/DESC, current-group()/EXT_DESC)"/>
<br />
<xsl:value-of "concat(current-group()/LINE_NOTE)" />
<br />
<xsl:value-of "concat(current-group()/NOTE)" />
</td>
<td><xsl:value-of select="current-group()/QTY" /></td>
<td><xsl:value-of select="current-group()/ADDTL_NOTE_DETAIL/NOTE" /></td>
</tr>
</xsl:for-each-group>
</table>
(由于OP有XSLT 2.0,这个答案的其余部分已经过时了。)
如果是1.0,那么最好的选择是Muenchian grouping。对于识别组的步骤(步骤1),您将使用类似
的键<xsl:key name="LINE_INFO-by-section" match="LINE_INFO"
use="generate-id((. | preceding-sibling::LINE_INFO)[ITEM_ID][last()])" />
迭代群组:
<xsl:for-each select="LINE_INFO[ITEM_ID]">
<xsl:copy>
迭代群组成员:
<xsl:variable name="section-starter-id" select="generate-id(.)" />
<xsl:for-each select="key('LINE_INFO-by-section', $section-starter-id))">
<xsl:copy-of select="node()|@*" />
</xsl:for-each>
</xsl:copy>
</xsl:for-each>
(未测试)。
答案 2 :(得分:1)
这个XSLT 2.0样式表:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<xsl:for-each-group select="LINE_INFO"
group-starting-with="LINE_INFO[ITEM_ID]">
<xsl:copy>
<xsl:apply-templates select="current-group()/node()"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
使用此输入:
<root>
<LINE_INFO>
<ITEM_ID>some_part_num</ITEM_ID>
<DESC>some_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
<LINE_INFO>
<EXT_DESC>more_description_for_some_part_num</EXT_DESC>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>some_other_part_num</ITEM_ID>
<DESC>some_other_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
<LINE_INFO>
<EXT_DESC>more_description_for_some_other_part_num</EXT_DESC>
</LINE_INFO>
<LINE_INFO>
<LINE_NOTE>This is a note related to some_other_part_num</LINE_NOTE>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>yet_another_part_num</ITEM_ID>
<DESC>yet_another_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>
</root>
输出:
<LINE_INFO>
<ITEM_ID>some_part_num</ITEM_ID>
<DESC>some_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
<EXT_DESC>more_description_for_some_part_num</EXT_DESC>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>some_other_part_num</ITEM_ID>
<DESC>some_other_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
<EXT_DESC>more_description_for_some_other_part_num</EXT_DESC>
<LINE_NOTE>This is a note related to some_other_part_num</LINE_NOTE>
</LINE_INFO>
<LINE_INFO>
<ITEM_ID>yet_another_part_num</ITEM_ID>
<DESC>yet_another_part_num_description</DESC>
<QTY>nn</QTY>
<UNIT>uom</UNIT>
</LINE_INFO>