在 XSLT 2.0 中定义变量时使用 xsl:copy-of
Posted
技术标签:
【中文标题】在 XSLT 2.0 中定义变量时使用 xsl:copy-of【英文标题】:Using xsl:copy-of when defining a variable in XSLT 2.0 【发布时间】:2020-11-21 05:38:10 【问题描述】:我(在一个虚构的简化世界中)有一个基本的源 XML 结构:
<?xml version="1.0"?>
<library>
<book>
<language>french</language>
<title>Les Misérables</title>
</book>
<book>
<language>english</language>
<title>Great Expectations</title>
</book>
</library>
我使用 xsl:variable 的 select 属性定义了一个变量 myVar1
<xsl:variable name="myVar1" select="library/book[language='french']"/>
我在 xsl:variable 中定义了一个带有 xsl:copy-of 的变量 myVar2
<xsl:variable name="myVar2">
<xsl:copy-of select="library/book[language='french']"/>
</xsl:variable>
我希望 myVar1 和 myVar2 相同,但事实并非如此
<xsl:value-of select="$myVar1/title"/> <!--result: Les Misérables-->
<xsl:value-of select="$myVar2/title"/> <!--empty result-->
定义 myVar2 时有什么问题?如何表明我希望它作为结构化的可查询变量(如 myVar1)?如果我有几个条件语句来定义变量,使用 select 不方便。
这是完整的 XSLT 文件
<?xml version='1.0'?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<xsl:variable name="myVar1" select="library/book[language='french']"/>
<xsl:variable name="myVar2">
<xsl:copy-of select="library/book[language='french']"/>
</xsl:variable>
<xsl:value-of select="$myVar1/title"/>
<xsl:value-of select="$myVar2/title"/>
</xsl:template>
</xsl:stylesheet>
【问题讨论】:
【参考方案1】:规则在https://www.w3.org/TR/xslt-30/#variable-values给出
快速总结:如果没有select
属性和as
属性,那么变量的值是一个新的文档节点,其中包含作为子元素复制的元素。正是这个额外的级别阻止了路径表达式的工作。对于select="library/book"
,变量的值是book
元素,对于序列构造函数,该值是一个文档节点,其子节点为book
。
【讨论】:
【参考方案2】:我希望 myVar1 和 myVar2 相同
但它们不相同:
第一个变量包含对book
节点的引用
源文件。
第二个变量包含book
节点在其自己的文档中的副本。
因此,指令:
<xsl:value-of select="$myVar2/title"/>
返回空,因为title
不是$myVar2
的子级。 $myVar2
的内容是复制的 book
节点 - 为了获取其子节点 title
的值,您需要使用:
<xsl:value-of select="$myVar2/book/title"/>
【讨论】:
【参考方案3】:我测试一下。
如果你输入了一个文件,你可以将它包含在<?xe.source [FILE_PATH]>
中
这是我的名为 Test_XML_1.xml 的 XML 文件:
<?xml version="1.0"?>
<library>
<book>
<language>french</language>
<title>Les Misérables</title>
</book>
<book>
<language>english</language>
<title>Great Expectations</title>
</book>
</library>
和你的一样。
这是我的 XSLT 代码:
<?xml version="1.0" encoding="UTF-8"?><?xe.source ../TemporaryFiles/Test_XML_1.xml#library?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output media-type="text/xml" method="xml"></xsl:output>
<xsl:variable name="myVar1" select="/library/book[language='french']"></xsl:variable>
<xsl:variable name="myVar2">
<xsl:copy-of select="/library/book[language='french']"></xsl:copy-of>
</xsl:variable>
<xsl:template match="/">
<root>
<xsl:copy-of select="$myVar1"></xsl:copy-of>
<xsl:copy-of select="$myVar2"></xsl:copy-of>
</root>
</xsl:template>
</xsl:stylesheet>
使用文件和 XSLT,我得到以下输出:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<book>
<language>french</language>
<title>Les Misérables</title>
</book>
<book>
<language>french</language>
<title>Les Misérables</title>
</book>
</root>
要正确使用变量,您需要在 <output>
和 <template>
元素之间声明它们。否则,您需要使用模板调用。就像在每种编程/脚本语言中一样。设置全局或局部变量。
顺便说一句。您需要清楚自己在 XPath 中的位置。
如果你说一次library/book[language='french']
,当你切换或退出模板时,你会在这条路径中感到很困惑。您要处理的问题是使用动态 XPath 或静态 XPath。
所以你也可以使用这个解决方案:
<?xml version="1.0" encoding="UTF-8"?><?xe.source ../TemporaryFiles/Test_XML_1.xml#library?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output media-type="text/xml" method="xml"></xsl:output>
<xsl:template match="/">
<xsl:variable name="myVar1" select="library/book[language='french']"></xsl:variable>
<xsl:variable name="myVar2">
<xsl:copy-of select="library/book[language='french']"></xsl:copy-of>
</xsl:variable>
<root>
<xsl:copy-of select="$myVar1"></xsl:copy-of>
<xsl:copy-of select="$myVar2"></xsl:copy-of>
</root>
</xsl:template>
</xsl:stylesheet>
要将路径的一部分添加到选定的路径,请使用:
<xsl:value-of select="//*[$myVar2]/title" />
那么应该可以工作了。
我希望这个小任务对你有所帮助;)
【讨论】:
谢谢,但我的目标是使用 myVar2 作为结构化元素。在输出中我不想要整个结构,我想查询$myVar2/title
并只显示这个标题
@user14027976 我在我的遮阳篷中添加了一条线。这应该可以解决您的问题;)【参考方案4】:
你可以使用
<xsl:variable name="myVar2" as="element()*">
<xsl:copy-of select="library/book[language='french']"/>
</xsl:variable>
让您的变量保存一系列元素节点,而不是包含元素节点的文档(片段)节点。
【讨论】:
以上是关于在 XSLT 2.0 中定义变量时使用 xsl:copy-of的主要内容,如果未能解决你的问题,请参考以下文章