我希望再次在这里得到帮助。这是我的示例输入XML:
<Report>
<RecordValues>
<Record>
<FieldValue fieldName="firm_name" fieldValue="Firm_1"/>
<FieldValue fieldName="firm_number" fieldValue="11"/>
<FieldValue fieldName="prepared_by" fieldValue="PARKER"/>
<FieldValue fieldName="contact_number" fieldValue="123456789"/>
<FieldValue fieldName="trade_date" fieldValue="2010-10-17"/>
<FieldValue fieldName="symbol" fieldValue="ADM"/>
</Record>
<Record>
<FieldValue fieldName="firm_name" fieldValue="Firm_1"/>
<FieldValue fieldName="firm_number" fieldValue="11"/>
<FieldValue fieldName="prepared_by" fieldValue="PARKER"/>
<FieldValue fieldName="contact_number" fieldValue="123456789"/>
<FieldValue fieldName="trade_date" fieldValue="2010-10-16"/>
<FieldValue fieldName="symbol" fieldValue="ACW"/>
</Record>
<Record>
<FieldValue fieldName="firm_name" fieldValue="Firm_2"/>
<FieldValue fieldName="firm_number" fieldValue="12"/>
<FieldValue fieldName="prepared_by" fieldValue="EDWARDS"/>
<FieldValue fieldName="contact_number" fieldValue="123456780"/>
<FieldValue fieldName="trade_date" fieldValue="2010-10-19"/>
<FieldValue fieldName="symbol" fieldValue="ADS"/>
</Record>
</RecordValues>
</Report>
以下是我需要获得的输出:
A Firm_1 11
B PARKER 123456789
C 2010-10-17 ADM
C 2010-10-16 ACW
T 4
A Firm_2 12
B EDWARDS 123456780
C 2010-10-19 ADS
T 3
如您所见,我需要按'firm_name'或'firm_number'对记录进行分组。每个组必须有一个类型为“A”的记录,一个类型为“B”的记录和多个“C”类型的记录。记录'T'是每组没有记录'T'的总和。输入XML已经排序。我找到了 Muenchian Method ,它正在对记录进行分组,但没有成功。显然我做错了什么。这是我写的XSLT:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:key name="value-by-firm" match="Report/RecordValues/Record/FieldValue" use="firm_number"/>
<xsl:template match="Record">
<xsl:for-each select="FieldValue/@fieldValue[count(. | key('value-by-firm', firm_number))]">
<xsl:text>A </xsl:text>
<xsl:value-of select="firm_name"/>
<xsl:text> </xsl:text>
<xsl:value-of select="firm_number"/>
<xsl:text>
</xsl:text>
<xsl:text>B </xsl:text>
<xsl:value-of select="prepared_by"/>
<xsl:text> </xsl:text>
<xsl:value-of select="contact_number"/>
<xsl:text>
</xsl:text>
<xsl:for-each select="key('value-by-firm', firm_number)">
<xsl:text>C </xsl:text>
<xsl:value-of select="trade_date"/>
<xsl:text> </xsl:text>
<xsl:value-of select="symbol"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
也许有另一种方法可以做到这一点。提前谢谢。
答案 0 :(得分:1)
您正在对“错误”事物进行分组,并错误地使用这些组。
Record
元素进行分组。例如,那些应该与您的xsl:key
匹配(use=...
属性应该引用公司名称)xsl:key
中的每个密钥,因此您处理所有值并忽略除组中第一个之外的所有值 - 并在那里执行整个组的处理。这意味着您的foreach应该选择与xsl:key
相同的元素并添加节点测试ala [count(. | reference-to-group[1]) = 1]
- 在这里,您忘记了[1]
和= 1
部分。然后是固定的XSLT文件(请注意,字段查找也稍有改动,我没有添加T
计算:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:key name="value-by-firm" match="/Report/RecordValues/Record" use="FieldValue[@fieldName='firm_number']/@fieldValue"/>
<xsl:template match="/">
<xsl:for-each select="/Report/RecordValues/Record[count(. | key('value-by-firm', FieldValue[@fieldName='firm_number']/@fieldValue)[1]) = 1]">
<xsl:text>A </xsl:text>
<xsl:value-of select="FieldValue[@fieldName='firm_name']/@fieldValue"/>
<xsl:text> </xsl:text>
<xsl:value-of select="FieldValue[@fieldName='firm_number']/@fieldValue"/>
<xsl:text>
</xsl:text>
<xsl:text>B </xsl:text>
<xsl:value-of select="FieldValue[@fieldName='prepared_by']/@fieldValue"/>
<xsl:text> </xsl:text>
<xsl:value-of select="FieldValue[@fieldName='contact_number']/@fieldValue"/>
<xsl:text>
</xsl:text>
<xsl:for-each select="key('value-by-firm', FieldValue[@fieldName='firm_number']/@fieldValue)">
<xsl:text>C </xsl:text>
<xsl:value-of select="FieldValue[@fieldName='trade_date']/@fieldValue"/>
<xsl:text> </xsl:text>
<xsl:value-of select="FieldValue[@fieldName='symbol']/@fieldValue"/>
<xsl:text>
</xsl:text>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
编辑:最后一点:鉴于此数据模式,您正在做的事情不是XSLT的优势之一。看起来你有一个数据结构可以自然地转换为更清晰的模式(例如,其中名称 - 值对由XML的自然名称 - 值对表示;即属性)。或者,您可能希望将其导入“真正的”编程语言(此数据几乎肯定来自此处),其中未表示诸如FieldValue元素和fieldName和fieldValue属性之类的所有内容。基本上;虽然这可以通过XML + XSLT实现,但最终会得到一个更复杂,更脆弱的解决方案,而不是以更自然的方式表示它并使用更自然的工具处理它。
答案 1 :(得分:1)
此样式表:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kRecordByFirmAndContact" match="Record"
use="concat(FieldValue[@fieldName='firm_number']
/@fieldValue,
'+',
FieldValue[@fieldName='contact_number']
/@fieldValue)"/>
<xsl:template
match="Record
[count(.|key('kRecordByFirmAndContact',
concat(FieldValue
[@fieldName='firm_number']
/@fieldValue,
'+',
FieldValue
[@fieldName='contact_number']
/@fieldValue))[1])
= 1 ]">
<xsl:variable name="vRecords"
select="key('kRecordByFirmAndContact',
concat(FieldValue
[@fieldName='firm_number']
/@fieldValue,
'+',
FieldValue
[@fieldName='contact_number']
/@fieldValue))"/>
<xsl:value-of select="concat('A ',
*[@fieldName='firm_name']
/@fieldValue,
' ',
*[@fieldName='firm_number']
/@fieldValue,
'
',
'B ',
*[@fieldName='prepared_by']
/@fieldValue,
' ',
*[@fieldName='contact_number']
/@fieldValue,
'
')"/>
<xsl:apply-templates select="$vRecords" mode="RecordC"/>
<xsl:value-of select="concat('T ',count($vRecords) + 2,'
')"/>
</xsl:template>
<xsl:template match="Record" mode="RecordC">
<xsl:value-of select="concat('C ',
*[@fieldName='trade_date']
/@fieldValue,
' ',
*[@fieldName='symbol']
/@fieldValue,
'
')"/>
</xsl:template>
</xsl:stylesheet>
输出:
A Firm_1 11
B PARKER 123456789
C 2010-10-17 ADM
C 2010-10-16 ACW
T 4
A Firm_2 12
B EDWARDS 123456780
C 2010-10-19 ADS
T 3
注意:正如您所看到的,这并不复杂,但您的架构使代码如此冗长......看起来像数据转储的M $ XML格式。