xslt嵌套重点标签转换
问题描述:
我遇到了一些我的文件的问题,可以使用帮助解决它。我从HTML转换为XML。有时我对自己有一个<b>
或<u>
或<i>
标签,我用xslt嵌套重点标签转换
<xsl:template match="i">
<emphasis italic="yes">
<xsl:apply-templates select="*|@*|text()"/>
</emphasis>
</xsl:template>
或大胆的b和强调妳。
有时候,我有一个<b>
这些嵌套<u>
我用
<xsl:template match="b/u">
<xsl:apply-templates select="*|@*|text()"/>
</xsl:template>
这是摆脱u
<xsl:template match="b[u]">
<emphasis bold="yes" underline="yes">
<xsl:apply-templates select="*|@*|text()"/>
</emphasis>
</xsl:template>
这是对b
遵循转换通过u
。
现在我的问题是当它嵌套在嵌套在b
中的i
嵌套如何做。这是什么代码?
答
在回答你的眼前问题,以匹配u
嵌套在嵌套在b
的i
你这样做
<xsl:template match="b/i/u">
您还需要模板来处理母公司b
和i
<xsl:template match="b[i/u]">
<xsl:template match=b/i[u]">
但大概你想应付嵌套在任何顺序的元素?而且,对于每种可能的解释,编码模板都会变得非常混乱,而且您还必须担心两个匹配相同元素的模板。
相反,试试这个XSLT是更灵活一点,虽然不是特别优雅
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="i[parent::b|parent::u]" name="italic">
<xsl:attribute name="italic">yes</xsl:attribute>
<xsl:apply-templates select="*|@*|text()"/>
</xsl:template>
<xsl:template match="b[parent::i|parent::u]" name="bold">
<xsl:attribute name="bold">yes</xsl:attribute>
<xsl:apply-templates select="*|@*|text()"/>
</xsl:template>
<xsl:template match="u[parent::b|parent::i]" name="underline">
<xsl:attribute name="underline">yes</xsl:attribute>
<xsl:apply-templates select="*|@*|text()"/>
</xsl:template>
<xsl:template match="*[self::b|self::i|self::u][not(parent::b)][not(parent::i)][not(parent::u)]">
<emphasis>
<xsl:choose>
<xsl:when test="self::b">
<xsl:call-template name="bold"/>
</xsl:when>
<xsl:when test="self::i">
<xsl:call-template name="italic"/>
</xsl:when>
<xsl:when test="self::u">
<xsl:call-template name="underline"/>
</xsl:when>
</xsl:choose>
</emphasis>
</xsl:template>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
的想法是,你必须符合具有其他这样的元素作为父母i
,b
或u
元素模板。在这种情况下,您只需输出相关属性。
你也有最上面的i
,b
或u
元素(即具有父无其他元素等),您的输出强调元素相匹配的主模板。注意使用命名模板更简单,以避免代码重复。
当你将它应用到下面的XML
<test>
<b>bold</b>
<i>Italic</i>
<b><i>bold Italic</i></b>
<u><b><i>bold Italic underline</i></b></u>
</test>
以下是输出
<test>
<emphasis bold="yes">bold</emphasis>
<emphasis italic="yes">Italic</emphasis>
<emphasis bold="yes" italic="yes">bold Italic</emphasis>
<emphasis underline="yes" bold="yes" italic="yes">bold Italic underline</emphasis>
</test>
答
下面是一个简单和短期的解决方案:只有两个模板,没有明确的条件指令:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:my="my:my" exclude-result-prefixes="my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<my:names>
<n short="b">bold</n>
<n short="i">italic</n>
<n short="u">underline</n>
</my:names>
<xsl:variable name="vNames" select="document('')/*/my:names/*"/>
<xsl:template match=
"node()[not(contains('+b+i+u+', concat('+',name(),'+')))]
/*[contains('+b+i+u+', concat('+',name(),'+'))]
">
<emphasis>
<xsl:apply-templates select="." mode="emph"/>
</emphasis>
</xsl:template>
<xsl:template mode="emph"
match="*[contains('+b+i+u+', concat('+',name(),'+'))]">
<xsl:attribute name="{$vNames[@short=name(current())]}">yes</xsl:attribute>
<xsl:apply-templates select="node()" mode="emph"/>
</xsl:template>
</xsl:stylesheet>
当该变换被应用在下面的XML文档:
<test>
<b>bold</b>
<i>Italic</i>
<b><i>bold Italic</i></b>
<u><b><i>bold Italic underline</i></b></u>
</test>
有用,正确的结果产生:
<emphasis bold="yes">bold</emphasis>
<emphasis italic="yes">Italic</emphasis>
<emphasis bold="yes" italic="yes">bold Italic</emphasis>
<emphasis underline="yes" bold="yes" italic="yes">bold Italic underline</emphasis>