我有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>
如果某人有任何建议或解决方案,那就太棒了。
答案 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:element
和xsl: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>
中,因此它返回其值的位置也是如此。这导致最终输出中嵌套的段落标记。