我有这样的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,但我无法做到这一点。
答案 0 :(得分:0)
要做的第一件事就是将源XML格式化为适当的形式。
XML文档包含只有一个根标记(让我们称之为 main ) 此标记可以包含多个源标记(例如 object )。
每个标记(如您在字符串标记中所写)可以包含带有值的属性 (在您的情况下名称和订单),但它们之间必须是&#34; =&#34;登录。
在 object 标签的情况下,你记得要放一个&#34; /&#34;在结束标记中, 但是你在每个关闭的字符串标签中忘了它。
因此正确的输入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>