我需要将输入xml转换为另一个xml,它应该打印每个元素,如果元素具有特定属性(x或y),它应该打印它的值和内联文本。应该为每个输入元素发生。根据每个元素的层次结构,它应该添加缩进。
输入XML:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<tom x="1" y="2" z='11'>
<para x="3" y="4" z='22'>This is first para</para>
<para x="5" y="6" z='23'>This is seond para
<ol x="7">
<li x="8" y="9" z='24'>this is listitem</li>
<li x="9" y="10" z='25'>this is listitem</li>
</ol>
</para>
</tom>
<harry x='11' y='12'>
<para x='13' y='14'>This is third para <b x='13'>this is bold <i y='14'>this is italic uder bold</i></b></para>
</harry>
</root>
输出应该是;
<newXML>
<p>{root}</p>
<p> {tom}</p>
<p> [Start attribute x='1']</p>
<p> [Start attribute y='2']</p>
<p> {para}</p>
<p> [Start attribute x='3']</p>
<p> [Start attribute y='4']</p>
<p> This is first para</p>
<p> [end attribute x='3']</p>
<p> [end attribute y='4']</p>
<p> {para}</p>
<p> [Start attribute x='5']</p>
<p> [Start attribute y='6']</p>
<p> This is second para</p>
<p> {ol}</p>
<p> [Start attribute x='7']</p>
<p> {li}</p>
<p> [Start attribute x='8']</p>
<p> [Start attribute y='9']</p>
<p> this is listitem</p>
<p> [end attribute x='8']</p>
<p> [end attribute y='9']</p>
<p> {li}</p>
<p> [Start attribute x='9']</p>
<p> [Start attribute y='10']</p>
<p> this is listitem</p>
<p> [end attribute x='9']</p>
<p> [end attribute y='10']</p>
<p> [end attribute x='7']</p>
<p> [end attribute x='5']</p>
<p> [end attribute y='6']</p>
<p> [end attribute x='1']</p>
<p> [end attribute y='2']</p>
<p> {harry}</p>
<p> ....</p>
</newXML>
我正在尝试这样的事情,它对于'ol','b','i'等内联元素失败了。也无法缩进。
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
<xsl:element name="newXML">
<xsl:for-each select="root//*">
<p>
<xsl:text>{</xsl:text><xsl:value-of select="local-name(.)"/><xsl:text>}</xsl:text>
</p>
<xsl:if test="@x or @y">
<p><xsl:text>[Start attribute x=</xsl:text><xsl:value-of select="@x"/><xsl:text>]</xsl:text></p>
<p><xsl:text>[Start attribute y=</xsl:text><xsl:value-of select="@y"/><xsl:text>]</xsl:text></p>
</xsl:if>
<xsl:choose>
<xsl:when test="text()[1][(string-length(normalize-space(.)) = 0)]">
<p></p>
</xsl:when>
<xsl:otherwise>
<p>
<xsl:apply-templates/>
</p>
</xsl:otherwise>
</xsl:choose>
<xsl:if test="@x or @y">
<p><xsl:text>[end attribute x=</xsl:text><xsl:value-of select="@x"/><xsl:text>]</xsl:text></p>
<p><xsl:text>[end attribute y=</xsl:text><xsl:value-of select="@y"/><xsl:text>]</xsl:text></p>
</xsl:if>
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template match="*">
<xsl:choose>
<xsl:when test="self::ol and parent::para"></xsl:when>
<xsl:otherwise><xsl:apply-templates></xsl:apply-templates></xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:4)
这是一个与其他答案不同的答案,因为它实际上使用了XSLT / XPath 2.0功能,例如for
循环,xsl:function
和序列。既然你可以使用2.0,也可以利用它!
此外,应包含的属性以xsl:param
完成,并且可以在运行时传递。如果XML输入发生更改,则无需在XSLT中更改硬编码的属性名称。
XML输入
<root>
<tom x="1" y="2" z='11'>
<para x="3" y="4" z='22'>This is first para</para>
<para x="5" y="6" z='23'>This is seond para
<ol x="7">
<li x="8" y="9" z='24'>this is listitem</li>
<li x="9" y="10" z='25'>this is listitem</li>
</ol>
</para>
</tom>
<harry x='11' y='12'>
<para x='13' y='14'>This is third para <b x='13'>this is bold <i y='14'>this is italic uder bold</i></b></para>
</harry>
</root>
XSLT 2.0
<xsl:stylesheet version="2.0" xmlns:l="local" xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="l xs" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="include-attrs" select="('x','y')"/>
<xsl:function name="l:indent">
<xsl:param name="level"/>
<xsl:for-each select="1 to $level">
<xsl:text>    </xsl:text>
</xsl:for-each>
</xsl:function>
<xsl:template match="/">
<newXML>
<xsl:apply-templates/>
</newXML>
</xsl:template>
<xsl:template match="*">
<xsl:variable name="level" select="count(ancestor-or-self::*)-1"/>
<p>
<xsl:value-of select="l:indent($level)"/>
<xsl:value-of select="concat('{',local-name(),'}')"/>
</p>
<xsl:apply-templates select="@*[local-name()=$include-attrs]">
<xsl:with-param name="mode" select="'Start'"/>
<xsl:with-param name="level" select="$level"/>
</xsl:apply-templates>
<xsl:apply-templates/>
<xsl:apply-templates select="@*[local-name()=$include-attrs]">
<xsl:with-param name="mode" select="'End'"/>
<xsl:with-param name="level" select="$level"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="@*">
<xsl:param name="mode"/>
<xsl:param name="level"/>
<p>
<xsl:value-of select="l:indent($level)"/>
<xsl:value-of select="concat('[',$mode,' attribute ',local-name(),'=''',.,'''',']')"/>
</p>
</xsl:template>
<xsl:template match="text()">
<xsl:variable name="level" select="count(ancestor-or-self::*)"/>
<p>
<xsl:value-of select="l:indent($level)"/>
<xsl:value-of select="normalize-space(.)"/>
</p>
</xsl:template>
</xsl:stylesheet>
XML输出
<newXML>
<p>{root}</p>
<p> {tom}</p>
<p> [Start attribute x='1']</p>
<p> [Start attribute y='2']</p>
<p> {para}</p>
<p> [Start attribute x='3']</p>
<p> [Start attribute y='4']</p>
<p> This is first para</p>
<p> [End attribute x='3']</p>
<p> [End attribute y='4']</p>
<p> {para}</p>
<p> [Start attribute x='5']</p>
<p> [Start attribute y='6']</p>
<p> This is seond para</p>
<p> {ol}</p>
<p> [Start attribute x='7']</p>
<p> {li}</p>
<p> [Start attribute x='8']</p>
<p> [Start attribute y='9']</p>
<p> this is listitem</p>
<p> [End attribute x='8']</p>
<p> [End attribute y='9']</p>
<p> {li}</p>
<p> [Start attribute x='9']</p>
<p> [Start attribute y='10']</p>
<p> this is listitem</p>
<p> [End attribute x='9']</p>
<p> [End attribute y='10']</p>
<p> [End attribute x='7']</p>
<p> [End attribute x='5']</p>
<p> [End attribute y='6']</p>
<p> [End attribute x='1']</p>
<p> [End attribute y='2']</p>
<p> {harry}</p>
<p> [Start attribute x='11']</p>
<p> [Start attribute y='12']</p>
<p> {para}</p>
<p> [Start attribute x='13']</p>
<p> [Start attribute y='14']</p>
<p> This is third para</p>
<p> {b}</p>
<p> [Start attribute x='13']</p>
<p> this is bold</p>
<p> {i}</p>
<p> [Start attribute y='14']</p>
<p> this is italic uder bold</p>
<p> [End attribute y='14']</p>
<p> [End attribute x='13']</p>
<p> [End attribute x='13']</p>
<p> [End attribute y='14']</p>
<p> [End attribute x='11']</p>
<p> [End attribute y='12']</p>
</newXML>
答案 1 :(得分:1)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/root">
<newXML>
<xsl:apply-templates select="*"/>
</newXML>
</xsl:template>
<xsl:template match="*">
<p>
<xsl:text>{</xsl:text>
<xsl:value-of select="local-name(.)"/>
<xsl:text>}</xsl:text>
</p>
<xsl:if test="@x">
<p>
<xsl:text>[Start attribute x=</xsl:text>
<xsl:value-of select="@x"/>
<xsl:text>]</xsl:text>
</p>
</xsl:if>
<xsl:if test="@y">
<p>
<xsl:text>[Start attribute y=</xsl:text>
<xsl:value-of select="@y"/>
<xsl:text>]</xsl:text>
</p>
</xsl:if>
<xsl:variable name="mytext" select="normalize-space(./text())" />
<xsl:if test="$mytext">
<p>
<xsl:value-of select="$mytext"/>
</p>
</xsl:if>
<xsl:apply-templates select="*"/>
<xsl:if test="@x">
<p>
<xsl:text>[end attribute x=</xsl:text>
<xsl:value-of select="@x"/>
<xsl:text>]</xsl:text>
</p>
</xsl:if>
<xsl:if test="@y">
<p>
<xsl:text>[end attribute y=</xsl:text>
<xsl:value-of select="@y"/>
<xsl:text>]</xsl:text>
</p>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
使用您的示例输入,将生成以下输出:
<?xml version="1.0" encoding="utf-8"?>
<newXML>
<p>{tom}</p>
<p>[Start attribute x=1]</p>
<p>[Start attribute y=2]</p>
<p>{para}</p>
<p>[Start attribute x=3]</p>
<p>[Start attribute y=4]</p>
<p>This is first para</p>
<p>[end attribute x=3]</p>
<p>[end attribute y=4]</p>
<p>{para}</p>
<p>[Start attribute x=5]</p>
<p>[Start attribute y=6]</p>
<p>This is seond para</p>
<p>{ol}</p>
<p>[Start attribute x=7]</p>
<p>{li}</p>
<p>[Start attribute x=8]</p>
<p>[Start attribute y=9]</p>
<p>this is listitem</p>
<p>[end attribute x=8]</p>
<p>[end attribute y=9]</p>
<p>{li}</p>
<p>[Start attribute x=9]</p>
<p>[Start attribute y=10]</p>
<p>this is listitem</p>
<p>[end attribute x=9]</p>
<p>[end attribute y=10]</p>
<p>[end attribute x=7]</p>
<p>[end attribute x=5]</p>
<p>[end attribute y=6]</p>
<p>[end attribute x=1]</p>
<p>[end attribute y=2]</p>
<p>{harry}</p>
<p>[Start attribute x=11]</p>
<p>[Start attribute y=12]</p>
<p>{para}</p>
<p>[Start attribute x=13]</p>
<p>[Start attribute y=14]</p>
<p>This is third para</p>
<p>{b}</p>
<p>[Start attribute x=13]</p>
<p>this is bold</p>
<p>{i}</p>
<p>[Start attribute y=14]</p>
<p>this is italic uder bold</p>
<p>[end attribute y=14]</p>
<p>[end attribute x=13]</p>
<p>[end attribute x=13]</p>
<p>[end attribute y=14]</p>
<p>[end attribute x=11]</p>
<p>[end attribute y=12]</p>
</newXML>
如果这是令人满意的,我们可以在下面讨论缩进。
答案 2 :(得分:0)
我认为你可以使用它:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<newXML>
<xsl:apply-templates select="*"/>
</newXML>
</xsl:template>
<xsl:template match="*">
<p>{<xsl:value-of select="local-name()"/>}</p>
<xsl:apply-templates select="@*[local-name() = 'x' or local-name() = 'y']" mode='start'/>
<xsl:apply-templates select="child::text()[normalize-space(.) != '']"/>
<xsl:apply-templates select="child::*"/>
<xsl:apply-templates select="@*[local-name() = 'x' or local-name() = 'y']" mode='end'/>
</xsl:template>
<xsl:template match="@*[local-name() = 'x' or local-name() = 'y']" mode='start'>
<p>[Start attribute x ='<xsl:value-of select="."/>']</p>
</xsl:template>
<xsl:template match="@*[local-name() = 'x' or local-name() = 'y']" mode='end'>
<p>[end attribute x ='<xsl:value-of select="."/>']</p>
</xsl:template>
<xsl:template match="text()[normalize-space(.)!='']">
<p><xsl:value-of select="normalize-space(.)"/></p>
</xsl:template>
</xsl:stylesheet>
答案 3 :(得分:0)
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="root">
<p><xsl:value-of select="concat('{', name(), '}')"/></p>
<xsl:apply-templates></xsl:apply-templates>
</xsl:template>
<xsl:template match="root/child::*">
<p><xsl:value-of select="concat('	', '{', name(), '}')"/></p>
<xsl:for-each select="@*">
<xsl:choose>
<xsl:when test="position()!=3">
<p><xsl:value-of select="concat('	', '[Start attribute ', name(), '=', '"', ., '"', ']')"/></p>
</xsl:when>
</xsl:choose>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="root/child::*/child::*">
<p><xsl:value-of select="concat('		', '{', name(), '}')"/></p>
<xsl:for-each select="@*">
<xsl:choose>
<xsl:when test="position()!=3">
<p><xsl:value-of select="concat('		', '[Start attribute ', name(), '=', '"', ., '"', ']')"/></p>
</xsl:when>
</xsl:choose>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="root/child::*/child::*/text()">
<p><xsl:value-of select="concat('			', normalize-space(.))"/></p>
</xsl:template>
<xsl:template match="root/child::*/child::*/child::*">
<p><xsl:value-of select="concat('				', '{', name(), '}')"/></p>
<xsl:for-each select="@*">
<p><xsl:value-of select="concat('				', '[Start attribute ', name(), '=', '"', ., '"', ']')"/></p>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="root/child::*/child::*/child::*/text()">
<p><xsl:value-of select="concat('					', normalize-space(.))"/></p> </xsl:template>
<xsl:template match="root/child::*/child::*/child::*/child::*">
<p><xsl:value-of select="concat('					', '{', name(), '}')"/></p>
<xsl:for-each select="@*">
<xsl:choose>
<xsl:when test="position()!=3">
<p><xsl:value-of select="concat('					', '[Start attribute ', name(), '=', '"', ., '"', ']')"/></p>
</xsl:when>
</xsl:choose>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="root/child::*/child::*/child::*/child::*/text()">
<p><xsl:value-of select="concat('						', normalize-space(.))"/></p>
</xsl:template>
</xsl:stylesheet>