0

我现在被这个问题困扰了一段时间。我有一个这样的示例 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>,那么我需要为它创建一个 LIST_ITEM,<name>否则创建一个普通的 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>

任何人都可以从这里指导我或建议替代路线吗?

4

1 回答 1

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>
于 2013-07-17T10:12:28.033 回答