使用 Muenchian 方法对多个键进行 XSLT 分组 [英] XSLT grouping on multiple keys using Muenchian method

查看:32
本文介绍了使用 Muenchian 方法对多个键进行 XSLT 分组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是输入文件.

所有这些块都被包裹在一个 标签中,这个标签没有出现,不知道为什么?并且所有这些块都包含在一个顶级元素 中.

All these blocks are wrapped in a <allocfile> tag which is not appearing, dunno why? And all these blocks are wrapped in a top level element <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>

输入文件需要根据多个key进行排序和分组.我继续使用 concat 函数和 Muenchian 方法,但在网络上没有太大帮助.我使用的是 XSLT 1.0.

The input file needs to be sorted and grouped on the basis of multiple keys. I proceeded using the concat function and the Muenchian method but didn't much help from the web. I am using XSLT 1.0.

分组规则

  • 文件中的所有节点都将具有 1234.. 这将成为第一个按键分组并在输出中显示为

  • All the nodes in the file will have <hd1> with values 1234.. this becomes the first group by key and appears in the output as <Header1>

  • 分组的第二个键是节点代码.具有相同值的节点被分组在一起.显示为.代码头

第二个键是节点组G_HFUNoHy.如果所有这些节点的值都相同,则它们会组合在一起.它在输出中显示为

The second key is the group of nodes G_H, FUN, oH, y. If all these have the same values for nodes, they get grouped together. It appears in the output as <Header2>

节点

上没有分组发生><金额>.它们在每个组中都有不同的值.

No grouping happens on the nodes <alc>, <No>, <DT>, <AMOUNT>. They have distinct values within each group.

推荐答案

如果 hd1 元素总是 '1234' 那么你并没有真正按它们分组,但如果你是,你会定义一个像这样的简单键

If the hd1 element is always '1234' then you are not really grouping by them, but if you were you would define a simple key like so

<xsl:key name="header1" match="AllocFile" use="hd1" />

对于第二个键,您需要考虑代码元素

For the second key, you would need to take account of the Code element

<xsl:key name="header2" match="AllocFile" use="concat(hd1, '|', Code)" />

然后对于最后一个键,您将定义一个更复杂的键来处理所有元素

And then for the last key, you would define a more complicated key to cope with all the elements

<xsl:key name="header3" 
   match="AllocFile" 
   use="concat(hd1 '|', Code, '|', G_H, '|', FUN, '|', oH, '|', y)" />

请注意使用管道"字符作为分隔符.选择一个永远不会出现在任何选定元素中的定界符很重要.

Do note the use of the 'pipe' character as the delimiter. It is important to pick a delimited that would never occur in any of the selected elements.

然后,要查找不同的 header1 元素,您将查找首先出现在 header1 键中的元素

Then, to look for the distinct header1 elements, you would look for the elements which appear first in the header1 key

<xsl:apply-templates 
   select="AllocFile[generate-id() = generate-id(key('header1', hd1)[1])]" 
   mode="header1" />

要在每个 header1 元素中找到不同的 Code 元素,您可以执行以下操作

To find the distinct Code elements within each header1 element, you would do the following

<xsl:apply-templates 
   select="key('header1', hd1)
     [generate-id() = generate-id(key('header2', concat(hd1, '|', Code))[1])]" 
   mode="header2" /> 

最后,在每个代码组中,要找到不同的header3"元素,您将在第三个键中查找第一个元素

Finally, within each code group, to find the distinct 'header3' elements, you would look for the first elements within the third key

<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>

请注意在模板匹配上使用mode属性来区分所有匹配AllocFile元素的多个模板.

Do note the use of the mode attribute on the template matching to distinguish between the multiple templates all matching the AllocFile elements.

当应用于您的示例 XML 时,输出如下

When applied to your sample XML, the following is output

<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.通过修改匹配文档元素的初始模板,将它们包装在根元素中会很简单.

If you did have different hd1 elements, other than '1234' you would end up with multiple Header1 elements, and so your output would not be well-formed XML. It would be simple enough to wrap them in a root element though by modified the initial template matching the document element.

<xsl:template match="/XML">
   <Root>
      <xsl:apply-templates select="AllocFile[generate-id() = generate-id(key('header1', hd1)[1])]" mode="header1" />
   </Root>
</xsl:template>

这篇关于使用 Muenchian 方法对多个键进行 XSLT 分组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆