首页 文章

XSLT转换(xml到xml)

提问于
浏览
0

我有这样的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

    首先要做的是将源XML格式化为适当的形式 .

    • XML文档包含 only one 根标记(让我们称之为主标记),此标记可以包含多个源标记(例如对象) .

    • 每个标记(如您在字符串标记中所写)可以包含具有值的属性(在您的情况下为名称和顺序),但它们之间必须是"="符号 .

    • 在对象标记的情况下,您记得在结束标记中放置"/",但是在每个结束字符串标记中都忘记了它 .

    因此,正确的输入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:output indent = "yes"(第2行)开始,否则所有内容都将在一行中(难以阅读) .

    XML代码包含单个模板匹配主标记(第4行) .

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

    然后,第6行包含分组循环(for-each-group) . 分组的对象是对象元素(请参阅select子句),分组键是字符串子标记(相对于当前对象)的内容,其属性名称等于"order"(请参阅分组子句) .

    因此第一组包含对象标记No 1和2(它们都具有字符串名称= "order"标记,内容为"1",第二组包含对象标记No 3 .

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

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

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

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

    此元素具有名为"name"的属性(请参阅name子句),其值应为"item"(请参阅select子句) - 第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>
    

相关问题