在我的源XML中,任何元素都可以具有@n属性。如果有的话,我想在处理元素及其所有子元素之前输出。
例如
<line n="2">Ipsum lorem</line>
<verse n="5">The sounds of silence</verse>
<verse>Four score and seven</verse>
<sentence n="3">
<word n="1">Hello</word>
<word n="2">world</word>
</sentence>
我的模板与“line”,“verse”,“sentence”和“word”匹配。如果这些元素中的任何一个具有@n值,我想在元素模板生成的任何内容之前输出它。
以上可能会出现类似
的内容2 <div class="line">Ipsum lorem</span>
5 <span class="verse">The sounds of silence</span>
<span class="verse">Four score and seven</span>
3 <p class="sentence">
1 <span class="word">Hello</span>
2 <span class="word">world</span>
</p>
其中“line”,“verse”等模板生成了div,span和p元素。
我该如何看待这个问题? - 匹配属性,然后将模板应用于其父项? (它的语法是什么?)在每个元素的模板的开头放一个调用模板? (那没什么吸引力。)还有别的吗? (可能!)
我尝试了一些东西,但是得到了一个无限循环,或者什么都没有,或者处理属性然后是它的父亲的子节点,而不是父节点本身。
答案 0 :(得分:3)
为简化问题,我将XML中的映射放置在文档内数据结构中(可通过document()函数访问,无需参数)。现在只需要一个模板,只需要在一个地方对@n属性进行特殊处理。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<map>
<elt xml="line" html="class"/>
<elt xml="verse" html="span"/>
<elt xml="sentence" html="p"/>
<elt xml="word" html="span"/>
</map>
<xsl:template match="line|verse|sentence|word">
<xsl:if test="@n"><xsl:value-of select="@n"/> </xsl:if>
<xsl:element name="{document()/map/elt[@xml=name()]/@html}">
<xsl:attribute name="class"><xsl:value-of select="name()"/></xsl:attibute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
答案 1 :(得分:1)
以下是一种简单的方法:
<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="*/*[@n]">
<xsl:value-of select="concat('
', @n, ' ')"/>
<xsl:apply-templates select="self::*" mode="content"/>
</xsl:template>
<xsl:template match="*/*[not(@*)]">
<xsl:apply-templates select="." mode="content"/>
</xsl:template>
<xsl:template match="line" mode="content">
<div class="line"><xsl:apply-templates/></div>
</xsl:template>
<xsl:template match="verse | word" mode="content">
<span class="{name()}"><xsl:apply-templates mode="content"/></span>
</xsl:template>
<xsl:template match="sentence" mode="content">
<p class="sentence"><xsl:apply-templates/></p>
</xsl:template>
</xsl:stylesheet>
在提供的XML文档上应用此转换时:
<t>
<line n="2">Ipsum lorem</line>
<verse n="5">The sounds of silence</verse>
<verse>Four score and seven</verse>
<sentence n="3">
<word n="1">Hello</word>
<word n="2">world</word>
</sentence>
</t>
产生了想要的正确结果:
2 <div class="line">Ipsum lorem</div>
5 <span class="verse">The sounds of silence</span>
<span class="verse">Four score and seven</span>
3 <p class="sentence">
1 <span class="word">Hello</span>
2 <span class="word">world</span>
</p>
解释:正确使用模板和模式。