【问题标题】:Creating attribute nodes from HTML style attribute value by XSL通过 XSL 从 HTML 样式属性值创建属性节点
【发布时间】:2014-03-23 08:55:24
【问题描述】:

我正在尝试使用 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>

谢谢。

【问题讨论】:

    标签: xml xslt


    【解决方案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>
    

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

    【讨论】:

    • 在更改 $styleValue 名称后效果很好。非常感谢。
    【解决方案2】:

    这不是更简单吗?

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

    【讨论】:

    • 哇,我可以得到一些关于清晰 XPath 表达式的提示。非常感谢 michael.hor257k。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多