当 Child 节点实际上是 Parent 时如何使用 XSLT 重构 XML
How to Restructure XML using XSLT when the Child Node is actually the Parent
我的 ERP 系统中有一个结构非常糟糕的 XML 源,并且 Header 与 Detail 的 Parent/Child 关系是相反的,因为在运行时,parent(键)在处理第一个详细记录之前是未知的。这是由于旧 DB2 大型机应用程序的接口编写方式所致。不幸的是,我无权修改报告,也无权更改报告,因此我必须按原样处理源代码。
这是 XML 输出的样子:
<report>
<detail>
<header>
<keyfield>1231</keyfield>
<headerfield1>foo</headerfield>
<headerfield2>bar</headerfield2>
</header>
<keymatch>1231</keymatch>
<detailfield0>Line1</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line2</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line3</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line4</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line5</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<header>
<keyfield>1232</keyfield>
<headerfield1>boo</headerfield>
<headerfield2>far</headerfield2>
</header>
<keymatch>1232</keymatch>
<detailfield0>Line1</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line2</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line3</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line4</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line5</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
</report>
最终,我需要它的格式类似于以下内容:
<report>
<header>
<keyfield>1231</keyfield>
<headerfield1>foo</headerfield>
<headerfield2>bar</headerfield2>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line1</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line2</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line3</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line4</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line5</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
</header>
<header>
<keyfield>1232</keyfield>
<headerfield1>boo</headerfield>
<headerfield2>far</headerfield2>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line1</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line2</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line3</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line4</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line5</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
</header>
</report>
诚然,我对 XSLT 了解不多,但我学得很快,而且我发现这是我需要使用的工具。对于它的价值,这是 JD Edwards 9.1,我将使用 BI Publisher 通过 XSL 模板发送数据,以便进一步移交给 EDI 合作伙伴。
谢谢,
贾斯汀
这样试试:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/report">
<xsl:copy>
<xsl:for-each-group select="detail" group-starting-with="detail[header]">
<header>
<xsl:copy-of select="header/*"/>
<xsl:apply-templates select="current-group()"/>
</header>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="detail">
<xsl:copy>
<xsl:copy-of select="* except header"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
我的 ERP 系统中有一个结构非常糟糕的 XML 源,并且 Header 与 Detail 的 Parent/Child 关系是相反的,因为在运行时,parent(键)在处理第一个详细记录之前是未知的。这是由于旧 DB2 大型机应用程序的接口编写方式所致。不幸的是,我无权修改报告,也无权更改报告,因此我必须按原样处理源代码。
这是 XML 输出的样子:
<report>
<detail>
<header>
<keyfield>1231</keyfield>
<headerfield1>foo</headerfield>
<headerfield2>bar</headerfield2>
</header>
<keymatch>1231</keymatch>
<detailfield0>Line1</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line2</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line3</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line4</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line5</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<header>
<keyfield>1232</keyfield>
<headerfield1>boo</headerfield>
<headerfield2>far</headerfield2>
</header>
<keymatch>1232</keymatch>
<detailfield0>Line1</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line2</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line3</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line4</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line5</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
</report>
最终,我需要它的格式类似于以下内容:
<report>
<header>
<keyfield>1231</keyfield>
<headerfield1>foo</headerfield>
<headerfield2>bar</headerfield2>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line1</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line2</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line3</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line4</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1231</keymatch>
<detailfield0>Line5</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
</header>
<header>
<keyfield>1232</keyfield>
<headerfield1>boo</headerfield>
<headerfield2>far</headerfield2>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line1</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line2</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line3</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line4</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
<detail>
<keymatch>1232</keymatch>
<detailfield0>Line5</detailfield0>
<detailfield1>this is bad structure</detailfield1>
<detailfield2>and not my design</detailfield2>
</detail>
</header>
</report>
诚然,我对 XSLT 了解不多,但我学得很快,而且我发现这是我需要使用的工具。对于它的价值,这是 JD Edwards 9.1,我将使用 BI Publisher 通过 XSL 模板发送数据,以便进一步移交给 EDI 合作伙伴。
谢谢,
贾斯汀
这样试试:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/report">
<xsl:copy>
<xsl:for-each-group select="detail" group-starting-with="detail[header]">
<header>
<xsl:copy-of select="header/*"/>
<xsl:apply-templates select="current-group()"/>
</header>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="detail">
<xsl:copy>
<xsl:copy-of select="* except header"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>