2013-04-30 78 views
1

我遇到了一些我的文件的问题,可以使用帮助解决它。我从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嵌套如何做。这是什么代码?

回答

0

在回答你的眼前问题,以匹配u嵌套在嵌套在bi你这样做

<xsl:template match="b/i/u"> 

您还需要模板来处理母公司bi

<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> 

的想法是,你必须符合具有其他这样的元素作为父母ibu元素模板。在这种情况下,您只需输出相关属性。

你也有最上面的ibu元素(即具有父无其他元素等),您的输出强调元素相匹配的主模板。注意使用命名模板更简单,以避免代码重复。

当你将它应用到下面的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> 
0

下面是一个简单和短期的解决方案:只有两个模板,没有明确的条件指令

<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>