2013-04-30 120 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>