带动态路径的XSLT文档

时间:2011-11-23 18:57:02

标签: xslt dynamic path document xslt-1.0

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

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

2 个答案:

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

答案 1 :(得分:0)

我不太确定我是否正确地解决了你的问题,不过我会尝试一下。

当您尝试使用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的调用封装在<p>中,因此它返回其值的位置也是如此。这导致最终输出中嵌套的段落标记。

相关问题