我正在使用PHP5,我需要以下面的形式转换XML:
<list>
<item label="(1)">some text</item>
<item label="(2)">
<anotherNode>some text</anotherNode
<item label="a">some text</item>
<item label="b">some text</item>
</item>
</list>
进入这样的事情:
<list>
<item label="(1)">some text</item>
<item label="(2)">
<anotherNode>some text</anotherNode>
<list> <!-- opening new wrapper node-->
<item label="a">some text</item>
<item label="b">some text</item>
</list> <!-- closing new wrapper node-->
</item>
</list>
正如您在上面所看到的,我需要为任何未被’list’节点包装的’item’节点添加一个包装器节点.
将源xml转换为目标xml有哪些可能的解决方案?
更新:
注1:任何单个或一组< item>节点需要由< list>包装节点,如果它没有包裹.
注2:需要维护内容的顺序.
注3:
如果有< item> < anotherNode>之前和之后的节点.
它应该改变这个:
<list>
<item label="(1)">some text</item>
<item label="(2)">
<item label="a">some text</item>
<item label="b">some text</item>
<anotherNode>some text</anotherNode>
<item label="c">some text</item>
<item label="d">some text</item>
</item>
</list>
进入这个:
<list>
<item label="(1)">some text</item>
<item label="(2)">
<list> <!-- opening new wrapper node-->
<item label="a">some text</item>
<item label="b">some text</item>
</list> <!-- closing new wrapper node-->
<anotherNode>some text</anotherNode>
<list> <!-- opening new wrapper node-->
<item label="c">some text</item>
<item label="d">some text</item>
</list> <!-- closing new wrapper node-->
</item>
</list>
谢谢,
解决方法:
这种转变:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="item/item[1]">
<list>
<xsl:apply-templates mode="copy"
select=".| following-sibling::item"/>
</list>
</xsl:template>
<xsl:template match="item" mode="copy">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="item/item[not(position()=1)]"/>
</xsl:stylesheet>
当应用于提供的XML文档时:
<list>
<item label="(1)">some text</item>
<item label="(2)">
<anotherNode>some text</anotherNode>
<item label="a">some text</item>
<item label="b">some text</item>
</item>
</list>
产生想要的,正确的结果:
<list>
<item label="(1)">some text</item>
<item label="(2)">
<anotherNode>some text</anotherNode>
<list>
<item label="a">some text</item>
<item label="b">some text</item>
</list>
</item>
</list>
请注意:
>使用和覆盖Identity规则.
>抑制某些元素.
>使用不同模式处理某些元素.
更新:
OP增加了额外的要求:
“如果在另一个节点之前和之后有项目元素,那么每个这样的项目元素组必须包含在一个单独的列表中”
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kfollnonitem" match="item"
use="generate-id(preceding-sibling::*[not(self::item)][1])"/>
<xsl:key name="kprecnonitem" match="item"
use="generate-id(following-sibling::*[not(self::item)][1])"/>
<xsl:template match="node()|@*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[not(self::list)]/item[1]">
<list>
<xsl:apply-templates mode="copy"
select="key('kprecnonitem',
generate-id(following-sibling::*[not(self::item)][1])
)"/>
</list>
</xsl:template>
<xsl:template match=
"*[not(self::list) and item]/*[not(self::item)]">
<xsl:call-template name="identity"/>
<list>
<xsl:apply-templates mode="copy"
select="key('kfollnonitem', generate-id())"/>
</list>
</xsl:template>
<xsl:template match="item" mode="copy">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="item/item[not(position()=1)]"/>
</xsl:stylesheet>
在对XML文档执行此转换时:
<list>
<item label="(1)">some text</item>
<item label="(2)">
<item label="a">some text</item>
<item label="b">some text</item>
<anotherNode>some text</anotherNode>
<item label="c">some text</item>
<item label="d">some text</item>
</item>
</list>
产生了想要的正确结果:
<list>
<item label="(1)">some text</item>
<item label="(2)">
<list>
<item label="a">some text</item>
<item label="b">some text</item>
</list>
<anotherNode>some text</anotherNode>
<list>
<item label="c">some text</item>
<item label="d">some text</item>
</list>
</item>
</list>