Php 包装XML节点组
我正在使用PHP5,我需要以以下形式转换XML:Php 包装XML节点组,php,xml,xslt,Php,Xml,Xslt,我正在使用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"
<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>
一些文本
一些文本
正如您在上面看到的,我需要将包装器节点添加到任何尚未由“列表”节点包装的“项目”节点
将源xml转换为目标xml有哪些可能的解决方案
更新:
注1:如果
节点尚未包装,则任何单个或组
节点都需要由
节点包装
注2:需要维护内容的顺序
注3:
如果在
前后有
节点。
它应该改变这一点:
<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:template match="@*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="@*|node()[1]" />
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1]" />
</xsl:template>
<xsl:template match="*[not(self::list)]
/item[not(preceding-sibling::*[1][self::item])]">
<list>
<xsl:call-template name="identity"/>
</list>
<xsl:apply-templates select="following-sibling::node()
[not(self::item)][1]" />
</xsl:template>
<xsl:template match="*[not(self::list)]
/item[not(following-sibling::*[1][self::item])]">
<xsl:copy>
<xsl:apply-templates select="@*|node()[1]" />
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="kItemByFirstSibling"
match="item[preceding-sibling::*[1][self::item]]"
use="generate-id(preceding-sibling::item
[not(preceding-sibling::*[1][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"/>
<xsl:template match="*[not(self::list)]
/item[not(preceding-sibling::*[1][self::item])]"
priority="1">
<list>
<xsl:for-each select=".|key('kItemByFirstSibling',generate-id())">
<xsl:call-template name="identity"/>
</xsl:for-each>
</list>
</xsl:template>
</xsl:stylesheet>
此转换:
<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>
<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>
<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>
对以下XML文档执行此转换时:
<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>
<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>
<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>
一些文本
一些文本
一些文本
一些文本
一些文本
一些文本
生成所需的正确结果:
<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>
<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>
<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>
一些文本
一些文本
一些文本
一些文本
一些文本
一些文本
您在原始问题中没有提到这一点,因此可能不需要。但是,如果输入有多个需要包装的
元素序列,这些元素由其他同级元素彼此分离,例如:
<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>
一些文本
一些文本
一些文本
.好问题(+1)。请参阅我的答案,了解XSLT精神下的简短解决方案。@Benjamin Ortuzar:您忘记接受答案了吗?仍然不完全满意?@Dimitre:+1表示模式解决方案。@Dimitre:如果在
之前和之后都有
元素,会发生什么情况?您的解决方案将把它们全部放在
之前@本杰明,在这种情况下会发生什么?@LarsH:观察得好。未指定具有其他名称和项目列表的兄弟项的所需顺序。我的解决方案保留了第一个项
和任何非项同级项之间的相对(文档)顺序。我认为这是很自然的。如果需要另一种排序,那么很容易修改解决方案以满足新的需求,前提是在这些组的前面和后面都有元素,它们应该有自己的包装器。内容的顺序应该保留。@Benjamin Ortuzar和@LarsH:我已经更新了我的答案,以便解决方案满足最新的要求。:)@亚历杭德罗:看我对迪米特的评论。。。假设所有需要包装的项元素(即同一个非列表元素的子元素)都是连续的,那么这个方法就可以了。@LarsH:正如我在notes中所写的,第一个样式表将第一个项
之后的任何节点包装起来。第二个样式表包装任何项
,不包含列表
父项,相对顺序(同级之间)将是第一个项
的相对顺序。我认为这是一个公平的问题,但只在OP想要输出siblings列表
家长时才重要。我需要像第二个示例那样单独包装他们。