Xslt转换

时间:2011-07-07 09:30:34

标签: xml xslt xpath

我将使用XSLT转换将第一个XML转换为第二个XML

首先:

<Data> 
 <Time> 
  <ID>IDvalue1</ID> 
  <field1>PropertyValue1</field1> 
  <field2>PropertyName1</field2> 
 </Time> 
 <Time>
  <ID>IDvalue2</ID> 
  <field1>PropertyValue2</field1> 
  <field2>PropertyName1</field2> 
 </Time>
 <Time> 
  <ID>IDvalue1</ID> 
  <field1>PropertyValue3</field1> 
  <field2> PropertyName2</field2> 
 </Time> 
 <Time> 
  <ID>IDvalue2</ID> 
  <field1>PropertyValue4</field1> 
  <field2>PropertyName2</field2> 
 </Time>
</Data>
....

第二

<Data> 
 <Time> 
  <ID>IDvalue1</ID> 
  <PropertyName1>PropertyValue1</PropertyName1> 
  <PropertyName2>PropertyValue3</PropertyName2> 
 </Time> 
 <Time> 
  <ID>IDvalue2</ID> 
  <PropertyName1>PropertyValue2</ PropertyName1> 
  <PropertyName2>PropertyValue4</PropertyName2> 
 </Time> 
</Data>
.....

在第一个XML中,有许多具有相同值的ID节点。在第二个XML中,它们被编译成单个节点。在第一个XML中的每个ID之后有field1和field2节点。在第二个XML中,必须创建新节点,其中field2是标记名称,field1是value。这些新节点是从具有相同值的所有ID节点收集的。

你能帮我写一下XSLT代码吗?

3 个答案:

答案 0 :(得分:2)

使用此模板:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
  <xsl:output method="xml" indent="yes"/>

  <xsl:key name="k" match="Time" use="ID"/>

  <xsl:template match="Data">
    <Data>
      <xsl:apply-templates select="Time[generate-id(.) = generate-id(key('k', ID))]"/>
    </Data>
  </xsl:template>

  <xsl:template match="Time">
    <Time>
      <xsl:copy-of select="ID"/>
      <xsl:for-each select="key('k', ID)">
        <xsl:element name="{normalize-space(field2)}">
          <xsl:value-of select="field1"/>
        </xsl:element>
      </xsl:for-each> 
    </Time>
  </xsl:template>

</xsl:stylesheet>

输出:

<?xml version="1.0" encoding="utf-8"?>
<Data>
  <Time>
    <ID>IDvalue1</ID>
    <PropertyName1>PropertyValue1</PropertyName1>
    <PropertyName2>PropertyValue3</PropertyName2>
  </Time>
  <Time>
    <ID>IDvalue2</ID>
    <PropertyName1>PropertyValue2</PropertyName1>
    <PropertyName2>PropertyValue4</PropertyName2>
  </Time>
</Data>

答案 1 :(得分:2)

这是一个标准的分组问题。如果您搜索“XSLT分组”,您会发现大量的帮助。使用xsl:for-each-group指令在XSLT 2.0中进行分组非常容易,但在XSLT 1.0中非常棘手,正如polishchuk所证明的那样。 (就我个人而言,如果不先了解您使用的XSLT版本以及原因,我甚至不会尝试回答分组问题 - 在这两种情况下代码是如此不同。)

答案 2 :(得分:1)

Microsoft .NET框架尚不支持XSLT 2.0。但是,如果您打算使用ASP .NET中的XSLT,您可以轻松实现(@Michael Key)Saxon。有关详细信息,请参阅this topic

准备好后,您的分组解决方案将非常简单。这里有一个XSLT 2.0分组示例应用于您的问题:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes"/>

    <xsl:template match="Data">
        <Data>
            <xsl:for-each-group select="Time" group-by="ID">
                <Time>
                    <xsl:copy-of select="ID"/>
                    <xsl:apply-templates select="current-group()"/>
                </Time>
            </xsl:for-each-group>
        </Data>
    </xsl:template>

    <xsl:template match="Time">
        <xsl:element name="{field2}">
            <xsl:value-of select="field1"/>
        </xsl:element>
    </xsl:template>

</xsl:stylesheet>