我使用XML开始使用php进行项目,现在我需要应用转换,所以我第一次发现了XSL ......
我遇到了问题:如何创建XSL以进行以下转换: - 以“attrib-”开头的节点转换为父节点的属性
<a1>
<b1>
<attrib-c1>12</attrib-c1>
<c2>23</c2>
</b1>
</a1>
应该成为:
<a1>
<b1 c1="12">
<c2>23</c2>
</b1>
</a1>
我已经开始这样的解决方案了:
<xsl:stylesheet>
<xsl:output method="xml"/>
<xsl:template match="@*|*|text()">
<xsl:copy>
<xsl:apply-templates select="@*|*|text()"/>
</xsl:copy>
</xsl:template>
...
</xsl:stylesheet>
我需要一些帮助才能解决这个问题。提前谢谢......
答案 0 :(得分:3)
XML输入(修改为略微增加复杂性。)
<a1>
<b1 existing="attr">
<attrib-c1>12</attrib-c1>
<c2>23</c2>
<attrib-dh>DevNull</attrib-dh>
</b1>
</a1>
XSLT 1.0
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="text()|@*|comment()|processing-instruction()">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="*[starts-with(name(),'attrib')]" mode="attr"/>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*[starts-with(name(),'attrib')]"/>
<xsl:template match="*" mode="attr">
<xsl:attribute name="{substring-after(name(),'-')}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
XML输出
<a1>
<b1 c1="12" dh="DevNull" existing="attr">
<c2>23</c2>
</b1>
</a1>
答案 1 :(得分:1)
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity -->
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<!-- match elements with children like attrib- and copy/pass -->
<xsl:template match="*[*[starts-with(name(.),'attrib')]]">
<xsl:copy>
<xsl:apply-templates select="*[starts-with(name(.),'attrib')]"/>
<xsl:apply-templates select="@*|*[not(starts-with(name(.),'attrib'))]"/>
</xsl:copy>
</xsl:template>
<!-- match elements like attrib- and output them as attribute -->
<xsl:template match="*[starts-with(name(.),'attrib')]">
<xsl:attribute name="{substring-after(name(.),'attrib-')}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
答案 2 :(得分:1)
这几乎与DevNull的解决方案相同,但是如果现有属性与子元素定义的新属性之间存在冲突,后者将取代前者:< / p>
<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()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:copy>
<xsl:apply-templates select="@*"/>
<xsl:apply-templates mode="attr" select="*[starts-with(name(), 'attrib-')]"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template mode="attr" match="*[starts-with(name(), 'attrib-')]">
<xsl:attribute name="{substring-after(name(), 'attrib-')}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:template>
<xsl:template match="*[starts-with(name(), 'attrib-')]"/>
</xsl:stylesheet>
将此转换应用于以下XML文档:
<a1>
<b1 existing="attr" x="Y">
<attrib-new>12</attrib-new>
<c2>23</c2>
<attrib-new2>ABCD</attrib-new2>
<attrib-x>Z</attrib-x>
</b1>
</a1>
产生了想要的正确结果:
<a1>
<b1 existing="attr" x="Z" new="12" new2="ABCD">
<c2>23</c2>
</b1>
</a1>