我尝试转换由多个来源生成的XML。如果我将文本直接输入到"选择值"语句中,则它会按预期工作。但是,一旦我尝试使用变量,它就不会再起作用了。
如果我在XSL中使用变量:for-east语句,它也可以正常工作。这是正常工作的XSL
<xsl:variable name="crm_acc" select="account" />
<xsl:variable name="nav_acc" select="kontakt" />
<xsl:variable name="crm_fname" select="firstname" />
<xsl:variable name="nav_fname" select="fname" />
<TreeView>
<xsl:for-each select="$crm_acc | $nav_acc">
<TreeViewItem Header="Item">
<TreeViewItem Header="Firstname:" >
<xsl:value-of select="firstname | fname" />
</TreeViewItem>
</TreeViewItem>
</xsl:for-each>
</TreeView>
但是,如果我使用xsl:选择值之内的变量,那只是在下一个代码块中指定的不起作用。我尝试了很多组合,例如仅将一个变量与" firstName"," firstName | fname"一起使用,试图concat(...)文本等...
<TreeView>
<xsl:for-each select="$crm_acc | $nav_acc">
<TreeViewItem Header="Item">
<TreeViewItem Header="Firstname:" >
<xsl:value-of select="$crm_fname | $nav_fname" />
</TreeViewItem>
</TreeViewItem>
</xsl:for-each>
</TreeView>
输入XML:
<?xml version='1.0'?>
<root>
<account system="CRM">
<firstname>test1</firstname>
</account>
<account system="CRM">
<firstname>test2</firstname>
</account>
<kontakt system="NAV">
<erstername>nav1</erstername>
</kontakt>
</root>
只有在变量中指定的"帐户/firstName"时才能获得结果。但是,这样,我总是只有在每个详细的迭代中才能获得第一个元素的价值。似乎它在指定变量时会丢失上下文(处理器当前位于"帐户"实体中,应该选择" firstName作为子节点)。
我读到,在XSLT 1.0到2.0的选择值语句中发生了一些变化,但我不完全理解区别是什么(我是XSLT的新手)。
我必须如何指定XSL才能工作?
更新:预期输出与代码块1
中<?xml version="1.0" encoding="UTF-8"?>
<TabItem xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Header="Xaml Accounts Tab">
<TreeView>
<TreeViewItem Header="CRM">
<TreeViewItem Header="Firstname:">test1</TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="CRM">
<TreeViewItem Header="Firstname:">test2</TreeViewItem>
</TreeViewItem>
<TreeViewItem Header="NAV">
<TreeViewItem Header="Firstname:">nav1</TreeViewItem>
</TreeViewItem>
</TreeView>
</TabItem>
编辑:我应该提到的是这些模板将/可以修改,因此如果所有"变量"都在一个地方,则会更容易。可能是目标不是"联系",而是其他内容,并且在整个文档中更改它是错误的和多余的。另外,这些变量在XMLReader读取的另一个过程中使用。我尝试使配置和冗余的麻烦尽可能低。
这是您可能想要探索的两种可能的方法:一个使用变量存储您可能希望调用的元素的所有可能的 name ;另一个假定其父元素的位置是已知的,因此名称并不重要。
以下样式显示了这两种方法,前者是父元素,后者的 firstName child。
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:variable name="CRM">
<name>account</name>
<name>kontakt</name>
</xsl:variable>
<xsl:template match="/">
<TreeView>
<xsl:for-each select="root/*[local-name()=exsl:node-set($CRM)/name]">
<TreeViewItem Header="{@system}">
<TreeViewItem Header="Firstname:" >
<xsl:value-of select="*[1]" />
</TreeViewItem>
</TreeViewItem>
</xsl:for-each>
</TreeView>
</xsl:template>
</xsl:stylesheet>
问题是XSLT中的变量是不变的。将它们视为常数。当你做
时<xsl:variable name="crm_fname" select="firstname" />
您在当前上下文中选择了" firstName"。我想该代码在<xsl:template match='root'>
上下文中,因此您选择了" root/firstName"。没有这样的节点,因此结果如预期为空。
当您调用for-east中的变量时,您只是在打印变量的内容,这是什么。
当您说变量为 account/firstname
时,它起作用,因为该节点存在,但是由于变量实际上是常数,因此它包含了第一个匹配的内容,并且任何其他更改该值的尝试都被忽略了。
在XSLT中,您必须忘记您知道的任何程序范例。您应该在不适当的情况下避免使用xsl:for-each
,然后编写单独的模板。
同样,在您的情况下也无需使用变量。也就是说,使用它们并非不可能,但是,正如@helderdarocha所指出的那样,您必须意识到它们的不变性和 context 。
。在您显示的样式表中,大多数变量很可能是空的,因为您选择的元素在该上下文中不存在。要选择元素,无论它们在层次结构中的位置如何,请用//
开始表达式。
样式表
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/root">
<TabItem xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Header="Xaml Accounts Tab">
<TreeView>
<xsl:apply-templates/>
</TreeView>
</TabItem>
</xsl:template>
<xsl:template match="account|kontakt">
<TreeViewItem Header="{@system}">
<xsl:apply-templates/>
</TreeViewItem>
</xsl:template>
<xsl:template match="firstname|erstername">
<TreeViewItem Header="Firstname:">
<xsl:value-of select="."/>
</TreeViewItem>
</xsl:template>
</xsl:stylesheet>
输出
<?xml version="1.0" encoding="UTF-8"?>
<TabItem xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Header="Xaml Accounts Tab">
<TreeView>
<TreeViewItem xmlns="" Header="CRM">
<TreeViewItem Header="Firstname:">test1</TreeViewItem>
</TreeViewItem>
<TreeViewItem xmlns="" Header="CRM">
<TreeViewItem Header="Firstname:">test2</TreeViewItem>
</TreeViewItem>
<TreeViewItem xmlns="" Header="NAV">
<TreeViewItem Header="Firstname:">nav1</TreeViewItem>
</TreeViewItem>
</TreeView>
</TabItem>