具有动态路径的 XSLT 文档
我有 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>
如果有人有任何建议或解决方案,那就太棒了。
I have XSLT 1.0 standard.
I have one dynamic XML from server which is quite simple and second XML as configuration. 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. 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.
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
由于您已经知道基于
$lang
的元素名称,因此您可以完全消除getvalueofnode
模板。我还删除了所有
xsl:element
和xsl:attribute
。通常可以通过直接对元素进行编码并使用 AVT(属性值模板) 用于属性。上面的样式表使用 XML 输入文件生成以下输出(使用 Saxon 6.5.5 和 Saxon-HE 9.3.0.5 进行测试):
Since you already know the name of the element based on
$lang
, you can eliminate thegetvalueofnode
template all together.I also got rid of all the
xsl:element
andxsl:attribute
. These can normally be avoided by coding the elements directly and using AVT (attribute value templates) for the attributes.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):
我不太确定我是否正确地解决了你的问题,但我还是会尝试一下。
当您尝试使用
getvalueofnode
模板获取值时,您将提供/header/en
作为路径。该模板将截断第一个斜杠之前的字符串,并在您的配置中查找具有该名称的元素。恰好被截断的值是空字符串,这会导致您的模板在配置中查找没有名称(不存在)的元素。因此,在第二次调用(第一次递归调用)中,
$content
将是一个空的结果树片段。因为它不包含斜杠,所以您的模板会打印不存在的值,因此也会打印一个空的结果树片段。由于空树片段在打印时会转换为空字符串,因此您的输出将是:关于解决方案:只需在第一次调用模板时删除前导斜杠即可。这就是用途:
您的转换将产生英文标题。
顺便说一句,您对
getvalueofnode
的调用封装在中,它返回值的地方也是如此。这会导致最终输出中出现嵌套的段落标签。
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. 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). 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:Regarding a solution: Just remove the leading slash when calling your template for the first time. That's use:
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. This leads to nested paragraph tags in the final output.