XSLT转换(xml到xml)

时间:2017-02-14 12:03:45

标签: xml xslt

我有这样的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转换为这个结构:

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

我想用XSLT动态转换输入XML,但我无法做到这一点。

1 个答案:

答案 0 :(得分:0)

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

  1. XML文档包含只有一个根标记(让我们称之为 main ) 此标记可以包含多个源标记(例如 object )。

  2. 每个标记(如您在字符串标记中所写)可以包含带有值的属性 (在您的情况下名称订单),但它们之间必须是&#34; =&#34;登录。

  3. object 标签的情况下,你记得要放一个&#34; /&#34;在结束标记中, 但是你在每个关闭的字符串标签中忘了它。

  4. 因此正确的输入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:输出缩进=&#34;是&#34; (第2行)开始,否则所有内容 将是一排(难以阅读)。

    XML代码包含一个 tempate 匹配标记(第4行)。

    它首先做的是复制(打开和关闭主要标签 - 第5行)。

    然后,第6行包含分组循环( for-each-group )。分组的对象是对象元素(参见 select 子句),分组键是 string 子标记的内容(相对于当前 object )属性 name 等于&#34; order&#34; (参见 group-by 子句)。

    所以第一组包含 object 标签No 1和2(它们都有 string name =&#34; order&#34; 标记内容为&#34; 1&#34;第二组包含 object 标记No.3。

    然后(对于每组源对象标签),我们创建一个输出对象元素(第7行)。

    此元素必须具有名为 order 的属性,其值为 当前分组键(第8行)。

    当前元素(输出对象)将包含来自每个元素的数据 当前组,所以我们必须编写 for-each 语句,循环遍历 所有源对象标记 - 当前组的内容(参见 select 子句,第9行)。

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

    这个元素有一个名为&#34; name&#34;的属性。 (参见 name 子句)和 它的价值应该是&#34; item&#34; (参见 select 子句) - 第11行。

    最后要做的是创建输出标记的内容 - child string 标记的值(相对于当前的对象 item 值的 name 属性 - 第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>