首页 文章

XSLT - 如何将模板应用于该类型的每个节点?

提问于
浏览
-1

我是xsl和函数式编程的新手,所以我将非常感谢这方面的帮助:

我有一个模板,可以转换一些xml并提供输出 . 问题是,有许多类型 xs:date 的元素,都在不同的上下文中,必须进行本地化 . 我使用这些xs:dates的子串串联来生成本地化的日期模式字符串 .

你可以猜到这会导致很多复制粘贴“substring-this和substring-that” . 如何编写一个模板,将自动将xs:date类型的所有元素转换为本地化字符串,保留所有上下文感知转换?

我的xsl是这样的:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">  
    <xsl:output method="html" encoding="utf-8"/>
        <xsl:template match="/">
        ...
        <input value="{substring(/select/a/date 9,2)}.{substring(/select/a/date, 6,2)}.{substring(/select/a/date 1,4)}">
        ...
        <!-- assume that following examples are also with substrings -->
        <div><xsl:value-of select="different-path/to_date"/></div>
        ...
        <table>
        <tr><td><xsl:value-of select="path/to/another/date"/></td></tr>
        </table>
        <apply-templates/>
        </xsl:template>
        <xsl:template match="something else">
        <!-- more dates here -->
        </xsl:template>
</xsl:stylesheet>

我希望我设法让我的问题清楚=)

UPD:这是一个xml的例子:

<REQUEST>
    <header>
        <... />
        <ref>
            <ref_date type="xs:date">1970-01-01</ref_date>
        </ref>
    </header>

    <general>
        <.../>
        <info>
            <.../>
            <date type="xs:date">1970-01-01</date>
            <ExpireDate type="xs:date">1970-01-01</ExpireDate>
            <RealDate type="xs:date">1970-01-01</RealDate>
            <templateDetails>template details</templateDetails>
            <effectiveDate type="xs:date">1970-01-01</effectiveDate>
        </info>

        <party>
            <.../>
                <date type="xs:date">1970-01-01</date>
        </party>

        <!-- many other parts of such kind -->
    </general>

</REQUEST>

至于输出,有许多不同的选择 . 主要的是这些值必须设置为不同html对象的值,例如表,输入字段等 . 您可以在xsl列表中看到一个示例 .

附:我正在使用xsl 1.0 .

2 回答

  • 1

    您可以做的是添加一个模板来匹配任何具有@type属性'xs:date'的元素,并在那里进行子串操作

    <xsl:template match="*[@type='xs:date']">
       <xsl:value-of select="translate(., '-', '/')" />
    </xsl:template>
    

    在这种情况下,我只是用斜杠替换连字符作为例子 .

    然后,而不是使用 xsl:value-of ....

    <div><xsl:value-of select="different-path/to_date"/></div>
    

    你可以用 xsl:apply-templates

    <div><xsl:apply-templates select="different-path/to_date"/></div>
    

    以此XSLT为例

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">        
        <xsl:output method="xml" indent="yes"/>
    
        <xsl:template match="*[@type='xs:date']">
            <xsl:copy>
                <xsl:value-of select="translate(., '-', '/')" />
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="@*|node()">
            <xsl:copy>
                <xsl:apply-templates select="@*|node()"/>
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    

    在这种情况下,所有这些XSLT正在做的是按原样复制XML文档,但更改日期元素 .

    如果您想将日期模板用于其他元素或值,您也可以将其设置为命名模板,就像这样

    <xsl:template match="*[@type='xs:date']" name="date">
        <xsl:param name="date" select="." />
        <xsl:value-of select="translate($date, '-', '/')" />
    </xsl:template>
    

    这样你就可以像函数一样调用它 . 例如,要格式化数据并添加为属性,您可以执行以下操作:

    <input>
       <xsl:attribute name="value">
           <xsl:call-template name="date">
              <xsl:with-param name="date" select="/select/a/date" />
           </xsl:call-template>
       </xsl:attribute>
    </input>
    
  • 1

    如果您进行了模式感知的XSLT 2.0转换,则不需要所有这些 type='xs:date' 属性:在模式中定义它作为日期就足够了 . 然后,您可以匹配属性

    <xsl:template match="attribute(*, xs:date)">

相关问题