我现在已经坚持这个问题一段时间了。我有一个样本XML文件,如下所示:
<Records>
<Record><Id>1</Id><Name>table_id</Name><Attribute></Attribute><Value>1</Value></Record>
<Record><Id>1</Id><Name>score</Name><Attribute></Attribute><Value>2.1</Value></Record>
<Record><Id>1</Id><Name>custom4</Name><Attribute>name</Attribute><Value>Custom411</Value></Record>
<Record><Id>1</Id><Name>custom4</Name><Attribute>name</Attribute><Value>Custom412</Value></Record>
<Record><Id>2</Id><Name>table_id</Name><Attribute></Attribute><Value>2</Value></Record>
<Record><Id>2</Id><Name>title</Name><Attribute></Attribute><Value>Title 2</Value></Record>
</Records>
我想使用以下格式的XSLT将所有ID和行合并到另一个XML文件中:
<RECORDS>
<RECORD>
<ITEM name="table_id" value="1"/>
<ITEM name="score" value="2.1"/>
<LIST name="custom4">
<LIST_ITEM value="custom411"/>
<LIST_ITEM value="custom412"/>
</LIST>
</RECORD>
<RECORD>
<ITEM name="table_id" value="2"/>
<ITEM name="title" value="Title 2"/>
</RECORD>
</RECORDS
<table_id> = <Id>
的基本价值。因此,对于每个<Id>
,我需要创建一个<RECORD>
。如果一个<Name>
存在多个相同<Id>
的值,那么我需要为<name>
创建一个LIST_ITEM,否则创建一个正常的ITEM。
到目前为止,我已经能够使用模板基于<Id>
对记录进行分组。但我无法使用此模板的输出生成最终输出:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="output">
<xsl:call-template name="groupById" />
</xsl:variable>
<OBJECTS>
<xsl:for-each select="$output/Root/Records">
<OBJECT>
<xsl:for-each select="Id/Record">
<ITEM>
<xsl:attribute name='name'>
<xsl:value-of select="Name" />
</xsl:attribute>
<xsl:attribute name='value'>
<xsl:value-of select="Value" />
</xsl:attribute>
</ITEM>
</xsl:for-each>
</OBJECT>
</xsl:for-each>
</OBJECTS>
</xsl:template>
<xsl:template name="groupById">
<Root>
<xsl:for-each-group select="/Records/Record" group-by="Id">
<Records>
<xsl:for-each-group select="current-group()" group-by="if(Id) then Id else 'no key'">
<!-- Copy attributes off the *first* Record element in the group -->
<xsl:copy-of select="current-group()[1]/Id"/>
<!-- Copy remaining children from *all* Record elements in the group -->
<xsl:copy-of select="current-group()"/>
</xsl:for-each-group>
</Records>
</xsl:for-each-group>
</Root>
</xsl:template>
</xsl:stylesheet>
有人可以从这里引导我或建议其他路线吗?
答案 0 :(得分:1)
这是一个简短但完整的XSLT 2.0样式表:
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="Records">
<RECORDS>
<xsl:for-each-group select="Record" group-by="Id">
<RECORD>
<ITEM name="table_id" value="{current-grouping-key()}"/>
<xsl:for-each-group select="current-group()[not(Name = 'table_id')]" group-by="Name">
<xsl:choose>
<xsl:when test="current-group()[2]">
<LIST name="{current-grouping-key()}">
<xsl:for-each select="current-group()">
<LIST_ITEM value="{Value}"/>
</xsl:for-each>
</LIST>
</xsl:when>
<xsl:otherwise>
<ITEM name="{Name}" value="{Value}"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</RECORD>
</xsl:for-each-group>
</RECORDS>
</xsl:template>
</xsl:stylesheet>
使用Saxon 9,它会转换输入
<Records>
<Record>
<Id>1</Id>
<Name>table_id</Name>
<Attribute></Attribute>
<Value>1</Value>
</Record>
<Record>
<Id>1</Id>
<Name>score</Name>
<Attribute></Attribute>
<Value>2.1</Value>
</Record>
<Record>
<Id>1</Id>
<Name>custom4</Name>
<Attribute>name</Attribute>
<Value>Custom411</Value>
</Record>
<Record>
<Id>1</Id>
<Name>custom4</Name>
<Attribute>name</Attribute>
<Value>Custom412</Value>
</Record>
<Record>
<Id>2</Id>
<Name>table_id</Name>
<Attribute></Attribute>
<Value>2</Value>
</Record>
<Record>
<Id>2</Id>
<Name>title</Name>
<Attribute></Attribute>
<Value>Title 2</Value>
</Record>
</Records>
进入以下结果:
<RECORDS>
<RECORD>
<ITEM name="table_id" value="1"/>
<ITEM name="score" value="2.1"/>
<LIST name="custom4">
<LIST_ITEM value="Custom411"/>
<LIST_ITEM value="Custom412"/>
</LIST>
</RECORD>
<RECORD>
<ITEM name="table_id" value="2"/>
<ITEM name="title" value="Title 2"/>
</RECORD>
</RECORDS>