通过XSL从HTML样式属性值创建属性节点

时间:2014-03-23 08:55:24

标签: xml xslt

我正在尝试使用xslt将XML文档更改为xsl:fo。在XML的一些元素节点中有HTML样式属性,如属性节点,我想将其值更改为分离的属性节点

XML样本是......

<books>
    <book>
        <price style="mycolor:red;myvalign:center;">10</price>
    </book>
</books>

我希望像这样改变它

<books>
    <book>
        <price mycolor="red" myvalign="center">10</price>
    </book>
</books>

我可以标记'style'属性节点的值(在这里得到stackoverflow的帮助)并将其渲染为键值配对但我不知道如何将这些键值对设置为调用节点的属性模板。

下面是我试过的xslt,但有错误。你能帮帮我吗?

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="xs"
    version="1.0">

    <xsl:template match="books">
        <xsl:element name="books">
            <xsl:apply-templates />
        </xsl:element>

    </xsl:template>

    <xsl:template match="book">
        <xsl:element name="book">
            <xsl:apply-templates />
        </xsl:element>
    </xsl:template>

    <xsl:template match="price">
        <xsl:variable name="style" select="./@style" />

        <xsl:variable name="result">
            <xsl:call-template name="tokenize">
                <xsl:with-param name="style" select="$style" />
            </xsl:call-template>
        </xsl:variable>

        <xsl:element name="price">
            <xsl:value-of select="$result"/>
            <xsl:value-of select="."/>  
        </xsl:element>
    </xsl:template>

    <xsl:template name="tokenize">
        <xsl:param name="style" />
        <xsl:variable name="styleFrag" select="substring-before($style, ';')" />
        <xsl:if test="$styleFrag">
            <xsl:variable name="styleKey" select="substring-before($styleFrag, ':')" />
            <xsl:variable name="styleVal" select="substring-after($styleFrag, ':')" />
            <xsl:variable name="concat1">&lt;xsl:attribute name=&apos;</xsl:variable>
            <xsl:variable name="concat2">&apos;&gt;&lt;xsl:value-of select=&apos;</xsl:variable>
            <xsl:variable name="concat3">&apos; /&gt;&lt;/xsl:attribute&gt;</xsl:variable>
            <xsl:variable name="concatted" select="concat($concat1, $styleKey, $concat2, $styleVal, $concat3)" />
            <xsl:value-of select="$concatted" />
            <xsl:call-template name="tokenize"> 
                <xsl:with-param name="style" select="substring-after($style,';')" /> 
            </xsl:call-template>
        </xsl:if>  
    </xsl:template>

</xsl:stylesheet>

谢谢。

2 个答案:

答案 0 :(得分:1)

更改

<xsl:template match="price">
    <xsl:variable name="style" select="./@style" />

    <xsl:variable name="result">
        <xsl:call-template name="tokenize">
            <xsl:with-param name="style" select="$style" />
        </xsl:call-template>
    </xsl:variable>

    <xsl:element name="price">
        <xsl:value-of select="$result"/>
        <xsl:value-of select="."/>  
    </xsl:element>
</xsl:template>

<xsl:template name="tokenize">
    <xsl:param name="style" />
    <xsl:variable name="styleFrag" select="substring-before($style, ';')" />
    <xsl:if test="$styleFrag">
        <xsl:variable name="styleKey" select="substring-before($styleFrag, ':')" />
        <xsl:variable name="styleVal" select="substring-after($styleFrag, ':')" />
        <xsl:variable name="concat1">&lt;xsl:attribute name=&apos;</xsl:variable>
        <xsl:variable name="concat2">&apos;&gt;&lt;xsl:value-of select=&apos;</xsl:variable>
        <xsl:variable name="concat3">&apos; /&gt;&lt;/xsl:attribute&gt;</xsl:variable>
        <xsl:variable name="concatted" select="concat($concat1, $styleKey, $concat2, $styleVal, $concat3)" />
        <xsl:value-of select="$concatted" />
        <xsl:call-template name="tokenize"> 
            <xsl:with-param name="style" select="substring-after($style,';')" /> 
        </xsl:call-template>
    </xsl:if>  
</xsl:template>

<xsl:template match="price">
    <xsl:variable name="style" select="./@style" />

    <price>
        <xsl:call-template name="tokenize">
            <xsl:with-param name="style" select="$style" />
        </xsl:call-template>

        <xsl:value-of select="."/>  
    </price>
</xsl:template>

<xsl:template name="tokenize">
    <xsl:param name="style" />
    <xsl:variable name="styleFrag" select="substring-before($style, ';')" />
    <xsl:if test="$styleFrag">
        <xsl:variable name="styleKey" select="substring-before($styleFrag, ':')" />
        <xsl:variable name="styleVal" select="substring-after($styleFrag, ':')" />
        <xsl:attribute name="{normalize-space($styleKey)}">
          <xsl:value-of select="$styleValue"/>
        </xsl:attribute>


        <xsl:call-template name="tokenize"> 
            <xsl:with-param name="style" select="substring-after($style,';')" /> 
        </xsl:call-template>
    </xsl:if>  
</xsl:template>

未经测试,但应该显示方法。

答案 1 :(得分:1)

这不是更简单吗?

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>

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

<xsl:template match="@style">
    <xsl:call-template name="tokenize-style">
        <xsl:with-param name="style" select="."/>
    </xsl:call-template>
</xsl:template>

<xsl:template name="tokenize-style">
    <xsl:param name="style"/>
        <xsl:if test="contains($style, ';')">
        <xsl:variable name="declaration" select="substring-before($style, ';')" />
        <xsl:attribute name="{normalize-space(substring-before($declaration, ':'))}">
            <xsl:value-of select="substring-after($declaration, ':')"/>
        </xsl:attribute>
            <!-- recursive call -->
            <xsl:call-template name="tokenize-style">
                <xsl:with-param name="style" select="substring-after($style, ';')" />
            </xsl:call-template>
        </xsl:if>
</xsl:template>

</xsl:stylesheet>