2

我对 XSLT 有非常基本的了解,我目前正在尝试实现一些我仍在尝试找出是否可能的东西。

可以是 XSLT 1.0 或 2.0

基本上这是我的 XML 的结构

   <?xml version="1.0" encoding="windows-1252"?>
<Root>
    <DataPage>
        <Record>
            <TEMP>xxx</TEMP>
            <DEBITNO>6250281</DEBITNO>
            <DOSSIERNUMMERINT>2012365</DOSSIERNUMMERINT>
            <ID>0123456789Z60</ID>
            <DATE>31/01/2013</DATE>
            <YEAR>2006</YEAR>
            <DESC>Test Item 1</DESC>
            <AMOUNT>           38170.0000000</AMOUNT>
            <HEAD>123</HEAD>
        </Record>
    </DataPage>
    <DataPage>
        <Record>
            <TEMP>xxx</TEMP>
            <DEBITNO>6250281</DEBITNO>
            <DOSSIERNUMMERINT>2012365</DOSSIERNUMMERINT>
            <ID>0123456789Z70</ID>
            <DATE>22/02/2013</DATE>
            <YEAR>2006</YEAR>
            <DESC>Test Item 2</DESC>
            <AMOUNT>           14410.0000000</AMOUNT>
            <HEAD>123</HEAD>
        </Record>
    </DataPage>
    <DataPage>
        <Record>
            <TEMP>xxx</TEMP>
            <DEBITNO>3849322</DEBITNO>
            <DOSSIERNUMMERINT>20132394</DOSSIERNUMMERINT>
            <ID>34958701223Z20</ID>
            <DATE>06/01/2013</DATE>
            <YEAR>2006</YEAR>
            <DESC>Test Item 1</DESC>
            <AMOUNT>           33811.0000000</AMOUNT>
            <HEAD>567</HEAD>
        </Record>
    </DataPage>
</Root>

我想要这个输出如下

<?xml version="1.0" encoding="windows-1252"?>
<Root>
    <DataPage>
        <Record>
            <TEMP>xxx</TEMP>
            <DEBITNO>6250281</DEBITNO>
            <DOSSIERNUMMERINT>2012365</DOSSIERNUMMERINT>
            <Line>
                <ID>0123456789Z60</ID>
                <DATE>31/01/2013</DATE>
                <YEAR>2006</YEAR>
                <DESC>Test Item 1</DESC>
                <AMOUNT>           38170.0000000</AMOUNT>
            </Line>
            <Line>
                <ID>0123456789Z70</ID>
                <DATE>22/02/2013</DATE>
                <YEAR>2006</YEAR>
                <DESC>Test Item 2</DESC>
                <AMOUNT>           14410.0000000</AMOUNT>
            </Line>
            <HEAD>123</HEAD>
        </Record>
    </DataPage>
    <DataPage>
        <Record>
            <TEMP>xxx</TEMP>
            <DEBITNO>3849322</DEBITNO>
            <DOSSIERNUMMERINT>20132394</DOSSIERNUMMERINT>
            <Line>
                <ID>34958701223Z20</ID>
                <DATE>06/01/2013</DATE>
                <YEAR>2006</YEAR>
                <DESC>Test Item 1</DESC>
                <AMOUNT>           33811.0000000</AMOUNT>
            </Line>
            <HEAD>567</HEAD>
        </Record>
    </DataPage>
</Root>

所以逻辑是合并所有具有相同 DEBITNO 的记录。

合并的规则是除了 ID、日期、年份、DESC 和 AMOUNT 之外的所有内容都可以从第一次出现中获取

ID、Date、Year、DESC 和 AMOUNT 需要放在一个标签中,所以如果有 2 条记录具有相同的 DEBITNO 将有 2 行,如果有 5 条记录具有相同的 DEBITNO 则结果记录将有 5 行项目。

我希望这是有道理的。

这样的事情可能吗?

问候,

4

2 回答 2

1

这是一个标准的分组问题。在 XSLT 2.0 中:

<xsl:template match="Root">
 <xsl:for-each-group select="DataPage/Record" group-by="DEBITNO">
  <DataPage>
    <Record>
     <xsl:copy-of select="TEMP, DEBITNO, DOSSIERNUMMERINT"/>
     <xsl:for-each select="current-group()">
       <Line>
         <xsl:copy-of select="ID, YEAR, DATE, DESC, AMOUNT"/>
       </
     </
   </
  </
 </
</   
于 2013-08-27T13:59:34.587 回答
0

在充分尊重 Kay 先生关于不提供解决方案的决定的情况下,xslt 1.0 中的这个解决方案解决了您的特定情况,也是更一般情况的解决方案,您可以拥有multiroot多个root元素并且需要本地分组

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" method="xml" indent="yes" />
  <xsl:key name ="k1" match="DataPage[
    not(preceding-sibling::DataPage/Record/DEBITNO = Record/DEBITNO)
    ]"
    use="generate-id()"/>

  <xsl:key name="k2" match="DataPage[
    preceding-sibling::DataPage/Record/DEBITNO = Record/DEBITNO]"
    use="generate-id(preceding-sibling::DataPage[
      Record/DEBITNO= current()/Record/DEBITNO
    ][last()])" />
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="DataPage"/>
  <xsl:template match="DataPage[key('k1',generate-id())]">
    <xsl:copy>
      <Record>
        <xsl:apply-templates select="Record/TEMP
          |Record/DEBITNO
          |Record/DOSSIERNUMMERINT"/>
        <xsl:for-each select=".|key('k2',generate-id())">
          <Line>
            <xsl:apply-templates select="Record/ID
              |Record/DATE
              |Record/YEAR
              |Record/DESC
              |Record/AMOUNT"/>
          </Line>
        </xsl:for-each>
        <xsl:apply-templates select="Record/HEAD"/>
      </Record>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

警告:似乎某些 XSLT 处理器不支持current()k2定义中使用函数

如果您想要一个更简单的解决方案只适合您的情况(不支持本地分组),您可以使用这种类似 Muenchian 的方法

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" method="xml" indent="yes" />
  <xsl:key name ="k" match="DataPage"
    use="Record/DEBITNO"/>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="DataPage"/>
  <xsl:template match="DataPage[ 
    generate-id() = generate-id(key('k', Record/DEBITNO)[1])
  ]">
    <xsl:copy>
      <Record>
        <xsl:apply-templates select="Record/TEMP
          |Record/DEBITNO
          |Record/DOSSIERNUMMERINT"/>
        <xsl:for-each select="key('k', Record/DEBITNO)">
          <Line>
            <xsl:apply-templates select="Record/ID
              |Record/DATE
              |Record/YEAR
              |Record/DESC
              |Record/AMOUNT"/>
          </Line>
        </xsl:for-each>
        <xsl:apply-templates select="Record/HEAD"/>
      </Record>
    </xsl:copy>
  </xsl:template>
</xsl:stylesheet>

在 xslt 1.0 中,这是一种众所周知的方法,即Muenchian 方法

我给自己写了一篇关于它和一些小的变化的论文。你也可以在这里找到

于 2013-08-27T18:23:46.797 回答