这是输入文件。
所有这些块都包含在<allocfile>
标签中,而不显示,不知道为什么?所有这些块都包含在顶级元素<xml>
中。
<XML>
<AllocFile>
<alc>1</alc>
<No>11/10</No>
<DT>20090401</DT>
<G_H>147</G_H>
<FUN>125487</FUN>
<oH>11</oH>
<y>9</y>
<AMOUNT>8000000</AMOUNT>
<Code>033195</Code>
<hd1>1234</hd1>
</AllocFile>
<AllocFile>
<alc>2</alc>
<No>14/10</No>
<DT>20090401</DT>
<G_H>147</G_H>
<FUN>125487</FUN>
<oH>11</oH>
<y>9</y>
<AMOUNT>8400000</AMOUNT>
<Code>033195</Code>
<hd1>1234</hd1>
</AllocFile>
<AllocFile>
<alc>3</alc>
<No>74/10</No>
<DT>20090401</DT>
<G_H>147</G_H>
<FUN>125487</FUN>
<oH>11</oH>
<y>9</y>
<AMOUNT>8740000</AMOUNT>
<Code>033195</Code>
<hd1>1234</hd1>
</AllocFile>
<AllocFile>
<alc>2</alc>
<No>74/10</No>
<DT>20090401</DT>
<G_H>117</G_H>
<FUN>125487</FUN>
<oH>19</oH>
<y>9</y>
<AMOUNT>74512</AMOUNT>
<Code>033118</Code>
<hd1>1234</hd1>
</AllocFile>
<AllocFile>
<alc>3</alc>
<No>14/10</No>
<DT>20090401</DT>
<G_H>117</G_H>
<FUN>125487</FUN>
<oH>19</oH>
<y>9</y>
<AMOUNT>986541</AMOUNT>
<Code>033147</Code>
<hd1>1234</hd1>
</AllocFile>
</XML>
输出
<Header1>
<Hd1>1234</Hd1>
<CodeHeader>
<Code>033195</Code>
<Header2>
<G_H>147</G_H>
<FUN>125487</FUN>
<oH>11</oH>
<y>9</y>
<allocheader>
<alc>1</alc>
<No>11/10</No>
<DT>20090401</DT>
<AMOUNT>8000000</AMOUNT>
</allocheader>
<allocheader>
<alc>2</alc>
<No>14/10</No>
<DT>20090401</DT>
<AMOUNT>8400000</AMOUNT>
</allocheader>
<allocheader>
<alc>3</alc>
<No>74/10</No>
<DT>20090401</DT>
<AMOUNT>8740000</AMOUNT>
</allocheader>
</Header2>
</CodeHeader>
<CodeHeader>
<Code>033118</Code>
<Header2>
<G_H>117</G_H>
<FUN>125487</FUN>
<oH>19</oH>
<y>9</y>
<allocheader>
<alc>2</alc>
<No>74/10</No>
<DT>20090401</DT>
<AMOUNT>74512</AMOUNT>
</allocheader>
</Header2>
</codeHeader>
<CodeHeader>
<Code>033147</Code>
<Header2>
<G_H>117</G_H>
<FUN>125487</FUN>
<oH>19</oH>
<y>9</y>
<allocheader>
<alc>3</alc>
<No>14/10</No>
<DT>20090401</DT>
<AMOUNT>986541</AMOUNT>
</allocheader>
</Header2>
</CodeHeader>
</Header1>
输入文件需要根据多个键进行排序和分组。我继续使用concat
函数和Muenchian方法,但没有从网上获得太多帮助。我正在使用XSLT 1.0。
分组规则
文件中的所有节点都会<hd1>
,其值为1234..
,这将成为第一个按键分组,并在输出中显示为<Header1>
第二个关键是节点组G_H
,FUN
,oH
,y
。如果所有这些节点具有相同的值,则它们将组合在一起。它在输出中显示为<Header2>
节点<alc>
,<No>
,<DT>
,<AMOUNT>
上没有分组。它们在每个组中都有不同的值。
答案 0 :(得分:7)
如果 hd1 元素始终为'1234',那么您实际上并不是按它们分组,但如果您是这样,则会定义一个简单的键,如此
<xsl:key name="header1" match="AllocFile" use="hd1" />
对于第二个密钥,您需要考虑代码元素
<xsl:key name="header2" match="AllocFile" use="concat(hd1, '|', Code)" />
然后对于最后一个键,您将定义一个更复杂的键来处理所有元素
<xsl:key name="header3"
match="AllocFile"
use="concat(hd1 '|', Code, '|', G_H, '|', FUN, '|', oH, '|', y)" />
请注意使用'pipe'字符作为分隔符。选择一个在任何选定元素中都不会出现的分隔符非常重要。
然后,要查找不同的 header1 元素,您需要查找首先出现在 header1 键中的元素
<xsl:apply-templates
select="AllocFile[generate-id() = generate-id(key('header1', hd1)[1])]"
mode="header1" />
要在每个 header1 元素中找到不同的代码元素,您可以执行以下操作
<xsl:apply-templates
select="key('header1', hd1)
[generate-id() = generate-id(key('header2', concat(hd1, '|', Code))[1])]"
mode="header2" />
最后,在每个代码组中,要查找不同的“header3”元素,您需要查找第三个键中的第一个元素
<xsl:apply-templates
select="key('header2', concat(hd1, '|', Code))
[generate-id() =
generate-id(key('header3', concat(hd1, '|', Code, '|', G_H, '|', FUN, '|', oH, '|', y))[1])]"
mode="header3" />
这是完整的XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:key name="header1" match="AllocFile" use="hd1"/>
<xsl:key name="header2" match="AllocFile" use="concat(hd1, '|', Code)"/>
<xsl:key name="header3" match="AllocFile" use="concat(hd1, '|', Code, '|', G_H, '|', FUN, '|', oH, '|', y)"/>
<xsl:template match="/XML">
<xsl:apply-templates select="AllocFile[generate-id() = generate-id(key('header1', hd1)[1])]" mode="header1"/>
</xsl:template>
<xsl:template match="AllocFile" mode="header1">
<Header1>
<Hd1>
<xsl:value-of select="hd1"/>
</Hd1>
<xsl:apply-templates select="key('header1', hd1)[generate-id() = generate-id(key('header2', concat(hd1, '|', Code))[1])]" mode="header2"/>
</Header1>
</xsl:template>
<xsl:template match="AllocFile" mode="header2">
<CodeHeader>
<xsl:copy-of select="Code"/>
<xsl:apply-templates select="key('header2', concat(hd1, '|', Code))[generate-id() = generate-id(key('header3', concat(hd1, '|', Code, '|', G_H, '|', FUN, '|', oH, '|', y))[1])]" mode="header3"/>
</CodeHeader>
</xsl:template>
<xsl:template match="AllocFile" mode="header3">
<Header2>
<xsl:copy-of select="G_H|FUN|oH|y"/>
<xsl:apply-templates select="key('header3', concat(hd1, '|', Code, '|', G_H, '|', FUN, '|', oH, '|', y))"/>
</Header2>
</xsl:template>
<xsl:template match="AllocFile">
<allocheader>
<xsl:copy-of select="alc|No|DT|AMOUNT"/>
</allocheader>
</xsl:template>
</xsl:stylesheet>
请注意在模板匹配中使用模式属性,以区分与 AllocFile 元素匹配的多个模板。
当应用于您的示例XML时,输出以下内容
<Header1>
<Hd1>1234</Hd1>
<CodeHeader>
<Code>033195</Code>
<Header2>
<G_H>147</G_H>
<FUN>125487</FUN>
<oH>11</oH>
<y>9</y>
<allocheader>
<alc>1</alc>
<No>11/10</No>
<DT>20090401</DT>
<AMOUNT>8000000</AMOUNT>
</allocheader>
<allocheader>
<alc>2</alc>
<No>14/10</No>
<DT>20090401</DT>
<AMOUNT>8400000</AMOUNT>
</allocheader>
<allocheader>
<alc>3</alc>
<No>74/10</No>
<DT>20090401</DT>
<AMOUNT>8740000</AMOUNT>
</allocheader>
</Header2>
</CodeHeader>
<CodeHeader>
<Code>033118</Code>
<Header2>
<G_H>117</G_H>
<FUN>125487</FUN>
<oH>19</oH>
<y>9</y>
<allocheader>
<alc>2</alc>
<No>74/10</No>
<DT>20090401</DT>
<AMOUNT>74512</AMOUNT>
</allocheader>
</Header2>
</CodeHeader>
<CodeHeader>
<Code>033147</Code>
<Header2>
<G_H>117</G_H>
<FUN>125487</FUN>
<oH>19</oH>
<y>9</y>
<allocheader>
<alc>3</alc>
<No>14/10</No>
<DT>20090401</DT>
<AMOUNT>986541</AMOUNT>
</allocheader>
</Header2>
</CodeHeader>
</Header1>
如果您确实有不同的 hd1 元素,那么除了'1234'之外,您最终会得到多个 Header1 元素,因此您的输出将不是格式良好的XML 。通过修改与文档元素匹配的初始模板,将它们包装在根元素中会很简单。
<xsl:template match="/XML">
<Root>
<xsl:apply-templates select="AllocFile[generate-id() = generate-id(key('header1', hd1)[1])]" mode="header1" />
</Root>
</xsl:template>