【问题标题】:XSLT document with dynamic path具有动态路径的 XSLT 文档
【发布时间】:2011-11-23 18:57:01
【问题描述】:

我有 XSLT 1.0 标准。 我有一个来自服务器的动态 XML,它非常简单,第二个 XML 作为配置。基于第一个(这是动态的)我必须从第二个中获取正确的节点信息。 这是第一份文件:

<?xml version="1.0" encoding="UTF-8" ?>
<response>
    <response>SUCCESS</response>
    <responsedata>
        <hit>
            <url>http://domain.com/page.html</url>
            <id>2437</id>
            <title>Page title</title>
            <language>en</language>
            ...
            ...
        </hit>
    </responsedata>
</response>

第二个配置 XML 用于页脚,页眉按语言划分。类似的东西:

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <set id="local">
        <header>
            <en>
                <![CDATA[
<div id="header">
    <p>English code</p>
</div>
                ]]>
            </en>
            <fr>
                <![CDATA[
<div id="header">
    <p>French code</p>
</div>
                ]]>
            </fr>
        </header>
    </set>
</config>

我需要从第二个 XML 中获取正确的语言相关代码。 我尝试了以下代码,但它不起作用:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="html" omit-xml-declaration="yes" encoding="utf-8" indent="yes" doctype-system="about:legacy-compat" />
    <xsl:variable name="configuration" select="document('settings.xml')/config/set[@id='local']" />
    <xsl:variable name="lang" select="response/responsedata/hit/language" />

    <xsl:template name="getvalueofnode">
        <xsl:param name="path" />
        <xsl:param name="context" select="$configuration" />
        <xsl:choose>
            <xsl:when test="contains($path,'/')">
                <xsl:call-template name="getvalueofnode">
                    <xsl:with-param name="path"    
                        select="substring-after($path,'/')" />
                    <xsl:with-param name="context" 
                        select="$context/*[name()=substring-before($path,'/')]" />
                </xsl:call-template>
            </xsl:when>
            <xsl:otherwise>
                <p>value: <xsl:value-of select="$context/*[name()=$path]" disable-output-escaping="yes" /></p>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:template>

    <xsl:template match="/">
        <xsl:element name="html">
            <xsl:attribute name="lang"><xsl:value-of select="$lang" /></xsl:attribute>
            <xsl:element name="head">
                <xsl:attribute name="lang"><xsl:value-of select="$lang" /></xsl:attribute>
            </xsl:element>
            <xsl:element name="body">
                <xsl:attribute name="lang"><xsl:value-of select="$lang" /></xsl:attribute>
                <p>lang: <xsl:value-of select="$lang" /></p>
                <p>
                <xsl:call-template name="getvalueofnode">
                    <xsl:with-param name="path" select="concat('/header/',$lang)" />
                </xsl:call-template>
                </p>
            </xsl:element>
        </xsl:element>
    </xsl:template>
</xsl:stylesheet>

如果有人有任何建议或解决方案,那就太好了。

【问题讨论】:

    标签: xslt dynamic path document xslt-1.0


    【解决方案1】:

    由于您已经知道基于$lang 的元素名称,您可以将getvalueofnode 模板一并消除。

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
      <xsl:output method="html" omit-xml-declaration="yes" encoding="utf-8" indent="yes" doctype-system="about:legacy-compat" />
      <xsl:variable name="configuration" select="document('settings.xml')/config/set[@id='local']" />
      <xsl:variable name="lang" select="response/responsedata/hit/language" />
    
      <xsl:template match="/">
        <html lang="{$lang}">
          <head lang="{$lang}"/>
          <body lang="{$lang}">
            <p>lang: <xsl:value-of select="$lang" /></p>
            <p>value: <xsl:value-of disable-output-escaping="yes" select="$configuration/header/*[name()=$lang]"/></p>
          </body>
        </html>
      </xsl:template>
    
    </xsl:stylesheet>
    

    我还删除了所有xsl:elementxsl:attribute。通常可以通过直接对元素进行编码并为属性使用AVT (attribute value templates) 来避免这些问题。

    上面的样式表使用您的 XML 输入文件生成以下输出(使用 Saxon 6.5.5 和 Saxon-HE 9.3.0.5 测试):

    <!DOCTYPE html
      SYSTEM "about:legacy-compat">
    <html lang="en">
       <head lang="en">
          <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
       </head>
       <body lang="en">
          <p>lang: en</p>
          <p>value: 
    
             <div id="header">
             <p>English code</p>
             </div>
    
    
          </p>
       </body>
    </html>
    

    【讨论】:

    • 它也可以正常工作。我想有一些更通用的方法来提取信息和操作数据。
    • 抱歉,如果我失败了,可能是意外。我无法改变它。我没有这个特权。对不起。
    【解决方案2】:

    我不太确定我是否正确解决了您的问题,但我还是会试一试。

    当您尝试使用getvalueofnode 模板获取您的价值时,您将提供/header/en 作为路径。模板将在第一个斜杠之前切掉字符串,并在您的配置中查找具有该名称的元素。恰好被截断的值是空字符串,这会导致您的模板在配置中查找没有名称(不存在)的元素。

    $content 因此在第二次调用(第一次递归调用)中将是一个空的结果树片段。因为这不包含斜线,所以您的模板打印不存在的值,因此也是一个空的结果树片段。由于空树片段在打印时会转换为空字符串,因此您的输出将是:

    <p>value: </p>
    

    关于解决方案:第一次调用模板时,只需删除前导斜杠即可。那就是使用:

    <xsl:call-template name="getvalueofnode">
        <xsl:with-param name="path" select="concat('header/',$lang)" />
    </xsl:call-template>
    

    然后您的转换将产生英文标题。

    顺便说一句,您对getvalueofnode 的调用被封装在&lt;p&gt; 中,它返回值的地方也是如此。这会导致最终输出中出现嵌套的段落标签。

    【讨论】:

    • 谢谢。你是绝对正确的。这是前导斜线的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-21
    • 2016-03-05
    • 2016-07-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多