2017-02-14 125 views
0

我有这样的XML:XSLT转换(XML到XML)

<object> 
    <string name "order">1<string> 
    <string name "item">1<string> 
</object> 
<object> 
    <string name "order">1<string> 
    <string name "item">2<string> 
</object> 
<object> 
    <string name "order">2<string> 
    <string name "item">1<string> 
</object> 

我想将XML转换到这个strukture:

<object order=1> 
    <string name "item">1<string> 
    <string name "item">2<string> 
</object> 
<object order=2> 
    <string name "item">1<string> 
</object> 

我想与动态转换输入XML XSLT,但我很难做到这一点。

+1

这是*分组*问题。做一个搜索 - 这可能是最经常被问到的XSLT问题。请注意,对于XSLT 1.0或2.0,答案是不同的。 –

回答

0

要做的第一件事就是将源XML转换为适当的形式。

  1. XML文档包含只有一个根标签(让我们称之为) 和该标签可以包含多个源代码(例如,对象)。

  2. 每个标签(如你在串写标签)可以包含属性 (在你的情况为了),但它们之间必须是“=”标志。

  3. 对象标签的情况下,你记得把在“/”关闭标签, 但你在每个关标签忘了。

所以正确的输入XML(需要更正后)为:

<main> 
    <object> 
    <string name="order">1</string> 
    <string name="item">1</string> 
    </object> 
    <object> 
    <string name="order">1</string> 
    <string name="item">2</string> 
    </object> 
    <object> 
    <string name="order">2</string> 
    <string name="item">1</string> 
    </object> 
</main> 

现在让我们倒在主业。 在描述中我把行号 - 引用到最终的解决方案。

我们从xsl:输出indent =“是”(第2行)开始,否则所有内容 将在单行(难以阅读)中。

该XML代码包含单个tempate匹配主要标记(第4行)。

它所做的第一件事是拷贝(开启和关闭标签 - 第5行)。

然后,第6行包含分组循环(,针对每个组)。细分电子邮件广告是对象元素中的对象(参见选择子句)和分组关键是子标签的含量(相对于当前对象)与属性名称等于“命令”(见组 - 由子句)。

所以第一组包含对象标签号1和2(它们都具有 字符串名称=“顺序”标签用的“1”的内容和所述第二组包含 对象标签号3。

然后(对于每组源对象标签)

我们创建输出对象元件(第7行),该元件必须具有一个ATT ribute命名为order与当前分组键(第8行)的值为 。

当前元素(输出对象)是包含在 当前组从每个元素数据,所以我们必须写的for-each语句,通过 所有源循环对象标签 - 的含量(请参阅选择子句,第9行)。

在此循环中,对于每个输入对象,我们创建了一个字符串元素(第10行)。

这个元素有一个名为“名”的属性(见条款)和 其值应为“项目”(见选择条款) - 行11

的最后一件事要做的就是创建输出标签的内容 - 与 属性的项目值 价值孩子标签的(相对于当前对象) - 行12

XSL中的所有其他行都是结束标记。

下面有一个完整的XSL解决方案。

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

    <xsl:template match="main"> 
    <xsl:copy> 
     <xsl:for-each-group select="object" group-by="string[@name='order']"> 
     <xsl:element name="object"> 
      <xsl:attribute name="order" select="current-grouping-key()"/> 
      <xsl:for-each select="current-group()"> 
      <xsl:element name="string"> 
       <xsl:attribute name="name" select="'item'"/> 
       <xsl:value-of select="string[@name='item']"/> 
      </xsl:element> 
      </xsl:for-each> 
     </xsl:element> 
     </xsl:for-each-group> 
    </xsl:copy> 
    </xsl:template> 

</xsl:transform>