简体   繁体   English

带有动态路径的 XSLT 文档

[英]XSLT document with dynamic path

I have XSLT 1.0 standard.我有 XSLT 1.0 标准。 I have one dynamic XML from server which is quite simple and second XML as configuration.我有一个来自服务器的动态 XML,它非常简单,第二个 XML 作为配置。 Base on first one (which is dynamic) I have to pick up proper nodes information from second one.基于第一个(这是动态的),我必须从第二个中获取正确的节点信息。 This is first document:这是第一个文件:

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

Second configuration XML is for footer, header divided by languages.第二个配置 XML 用于页脚,页眉按语言划分。 Something like that:类似的东西:

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

I need pick up proper language depended code from second XML.我需要从第二个 XML 中获取正确的语言相关代码。 I tried following code and it doesn't work:我尝试了以下代码,但它不起作用:

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

If some one has any suggestion or solution it will be fantastic.如果有人有任何建议或解决方案,那就太棒了。

Since you already know the name of the element based on $lang , you can eliminate the getvalueofnode template all together.由于您已经知道基于$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>

I also got rid of all the xsl:element and xsl:attribute .我还摆脱了所有xsl:elementxsl:attribute These can normally be avoided by coding the elements directly and using AVT (attribute value templates) for the attributes.这些通常可以通过直接对元素进行编码并对属性使用AVT(属性值模板)来避免。

The stylesheet above produces the following output using your XML input files (tested with Saxon 6.5.5 and Saxon-HE 9.3.0.5):上面的样式表使用您的 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>

I'm not too sure if I got your problem correctly however I'll give it a try nevertheless.我不太确定我是否正确解决了您的问题,但是我会尝试一下。

When you try to get your value with the getvalueofnode template you are supplying /header/en as path.当您尝试使用getvalueofnode模板获取您的值时,您将提供/header/en作为路径。 The template will the chop off the string before the first slash and look for an element with that name in your configuration.该模板将在第一个斜杠之前切断字符串,并在您的配置中查找具有该名称的元素。 It happens to be that the chopped off value is the empty string which results in your template looking for an element in the configuration without a name (that does not exist).碰巧切掉的值是空字符串,这会导致您的模板在配置中查找没有名称(不存在)的元素。

$content will therefore be an empty result tree fragment in the second call (first recursive call). $content因此在第二次调用(第一次递归调用)中将是一个空的结果树片段。 Because this doesn't contain a slash your template print the value that is not there and therefore an empty result tree fragment as well.因为这不包含斜杠,所以您的模板会打印不存在的值,因此也会打印一个空的结果树片段。 Since empty tree fragments are converted to an empty string when printed your output will just be:由于空树片段在打印时转换为空字符串,因此您的输出将是:

<p>value: </p>

Regarding a solution: Just remove the leading slash when calling your template for the first time.关于解决方案:第一次调用模板时,只需删除前导斜杠。 That's use:那是用:

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

Your transformation will then result in the English header.您的转换将导致英文标题。

By the way your call to getvalueofnode is encapsulated in <p> and so is the place where it returns its value.顺便说一下,您对getvalueofnode的调用封装在<p> ,因此它返回值的地方也是如此。 This leads to nested paragraph tags in the final output.这会导致最终输出中出现嵌套的段落标签。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM