XSLT根据条件

时间:2017-08-30 16:12:03

标签: html xslt

这是我的需要: 我有一个由多个嵌套SPAN组成的HTML文本。 一些跨度包括内联css。在那个内联CSS中,我需要将一些样式属性转换为" classic" HTML,就像。 某些跨度具有一个或多个要由HTML元素替换的属性。

以下是输入示例:

<HTML>
<SPAN>
    Some sentance including another 
    <SPAN STYLE="font-weight: bold;" >
        included bold block 
    </SPAN>
    with a tail in it and line breaks<BR/>
</SPAN>
<SPAN STYLE= "font-family: 'Helvetica';font-weight: bold;" >
    Another span with 1 attribute not to be taken into account and 1 to be
</SPAN>
<SPAN STYLE= "font-family: 'Helvetica';font-weight: bold;text-decoration:underline;" >
    Another span with two attributes to be taken into account
</SPAN>
</HTML>

我想要的结果是:

<HTML>
<p>Some sentance including another 
    <p><b>included bold block </b></p>
    with a tail in it and line breaks<BR/></p>
<p><b>Another span with 1 attribute not to be taken into account and 1 to be</b></p>
<p><b><u>Another span with two attributes to be taken into account</u></b></p>
</HTML>

我认为最好的方法是使用身份转换并使用模板来匹配属性,例如:

SPAN[contains(@STYLE, 'font-weight: bold;')

和:

SPAN[contains(@STYLE, 'text-decoration:underline;')]

这是我试过的......

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" omit-xml-declaration="yes"/>
    <xsl:strip-space elements="*"/>
    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="SPAN[contains(@STYLE, 'text-decoration:underline;')]">
        <xsl:element name="u">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="SPAN[contains(@STYLE, 'font-weight: bold;')]">
        <xsl:element name="b">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="SPAN">
        <!-- replacing SPAN into <p>elements -->
        <xsl:element name="p">
            <xsl:apply-templates/>
        </xsl:element>
    </xsl:template>

    <xsl:template match="SPAN/@STYLE"/>
    <!-- suppression of the old Style attribute-->
</xsl:stylesheet>

问题是,当它运行时,它只匹配其中一个或者 我想我错误地理解如何在模板中使用xsl:copy来要求模板评估SPAN并重新评估相同范围内的其他模板,但是我没有成功让它工作有或没有它...

我提前感谢你对此的看法。

祝你好运。

1 个答案:

答案 0 :(得分:0)

在这里,您可以使用XSLT 1.0中的模式进行操作

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" omit-xml-declaration="yes"/>

    <xsl:strip-space elements="*"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="SPAN[contains(@STYLE, 'text-decoration:underline;')]" mode="u">
        <u>
            <xsl:apply-templates/>
        </u>
    </xsl:template>

    <xsl:template match="SPAN" mode="u">
        <xsl:apply-templates/>
    </xsl:template>

    <xsl:template match="SPAN[contains(@STYLE, 'font-weight: bold;')]" mode="b">
        <b>
            <xsl:apply-templates select="." mode="u" />
        </b>
    </xsl:template>

    <xsl:template match="SPAN" mode="b">
        <xsl:apply-templates select="." mode="u" />
    </xsl:template>

    <xsl:template match="SPAN">
        <p>
            <xsl:apply-templates select="." mode="b" />
        </p>
    </xsl:template>
</xsl:stylesheet>

请注意,匹配SPAN[contains(...)]的模板的优先级高于匹配SPAN的模板。

因此,实际上您可以更改模板。对于SPAN标记,输出p节点,然后调用b模板以检查粗体。然后b模板调用u模板以检查下划线,然后此模板处理子项。您可以以类似的方式添加更多模板(因此b调用u,然后u调用ii处理子项。

编辑:如果您想避免为每个模板编写两个模板,您可以将每对模板合并为一个模板,如此

    <xsl:template match="SPAN" mode="b">
        <xsl:choose>
            <xsl:when test="contains(@STYLE, 'font-weight: bold;')">
                <b>
                    <xsl:apply-templates select="." mode="u" />
                </b>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="." mode="u" />
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

如果你可以使用XSLT 2.0,你可以使用优先级,而next-match代替,这会减少模板的数量

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output indent="yes" omit-xml-declaration="yes"/>

    <xsl:strip-space elements="*"/>

    <xsl:template match="node()|@*">
        <xsl:copy>
            <xsl:apply-templates select="node()|@*"/>
        </xsl:copy>
    </xsl:template>

    <xsl:template match="SPAN">
        <xsl:apply-templates />
    </xsl:template>

    <xsl:template match="SPAN[contains(@STYLE, 'text-decoration:underline;')]" priority="8">
        <u>
            <xsl:next-match />
        </u>
    </xsl:template>

    <xsl:template match="SPAN[contains(@STYLE, 'font-weight: bold;')]" priority="9">
        <b>
          <xsl:next-match />
        </b>
    </xsl:template>

    <xsl:template match="SPAN" priority="10">
        <p>
            <xsl:next-match />
        </p>
    </xsl:template>
</xsl:stylesheet>