我对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,日期,年份,DESC和AMOUNT需要放入标签中,因此如果有2个记录具有相同的DEBITNO,则会有2个行项目,如果有5个记录具有相同的DEBITNO,则结果记录将有5个订单项。
我希望这是有道理的。
这样的事情可能吗?
此致
答案 0 :(得分: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"/>
</
</
</
</
</
</
答案 1 :(得分:0)
对凯先生关于不提供解决方案的决定充分尊重,xslt 1.0中的这个解决了您的具体案例,也是一个解决方案,适用于您可以拥有 multiroot
<的更一般情况/ em>需要多个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 method。
我自己写了一篇关于它和一些小变化的论文。你也可以找到here