2011-07-07 40 views
2

我会使用XSLT转换XSLT转换

首先到第一个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代码吗?

+0

您可以在SO找到很多关于分组的问题/答案。但是,如果您是XSLT新手,分组可能很难理解并适用于您的用例。 +1为你明确的问题。 –

回答

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> 
+0

谢谢,你的回答很有用。如何将标签的名称传递给XSLT转换? (我的标签并不总是像

+0

@ Egor4eg,你可以在XSLT中传递参数,但有一些限制。看看这个主题:http://stackoverflow.com/questions/4807377/how-can-you-pass-in-a-parameter-to-an-xslt-that-c​​an-be-used-in-a-xslkey –

2

这是一个标准的分组问题。如果您搜索“XSLT分组”,您会找到大量帮助。 polishchuk已经证明,使用xsl:for-each-group指令在XSLT 2.0中编组非常容易,但在XSLT 1.0中非常棘手。 (就我个人而言,如果不先知道您正在使用哪个版本的XSLT以及为什么 - 在两种情况下代码是如此不同),我甚至不会尝试回答分组问题。)

+0

我是XSLT转换中的新手。从未做过。我没有尝试polishchuk的答案。我打算在几天内完成。 关于XSLT版本 - 我不确定。我正在使用ASP.NET 4.0。我应该使用哪个版本? – Egor4eg

1

Microsoft .NET Framework尚不支持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> 
+0

非常感谢。该解决方案看起来比XSLT 1.0版更好。但是我不打算使用任何额外的代码来处理2.0,因为我没有时间。所以,答案+1,我会用polishchuk的解决方案。 – Egor4eg