我尝试转换由多个源生成的XML片段。如果我直接在select-statement的value中输入文本,它就会按预期工作。但是一旦我尝试使用变量就不再有用了。
如果我在xsl:for-each语句中使用变量,它也可以正常工作。这是可行的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:value-of select中使用变量,它就不会像下一个代码块中指定的那样工作。我尝试了很多组合,例如只使用一个带有“firstname”,“firstname | fname”的变量,尝试连接(...)文本等......
<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>
只有我得到一个结果,因为我在变量中指定了“account / firstname”。但是这样我总是只在每次迭代中得到第一个元素的值。在指定变量时(处理器当前位于“帐户”实体内部并且应选择“firstname as a subnode”),似乎它会丢失上下文。
我读到从XSLT 1.0到2.0的select语句的值发生了变化,但我不完全明白它的区别(我对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读取的另一个进程中。我尽量避免配置和冗余的麻烦。
答案 0 :(得分:1)
以下是您可能想要探索的两种可能方法:一种使用变量来存储您可能希望调用的元素的所有可能名称;另一个假设其父元素中的元素的位置是已知的,因此该名称并不重要。
以下样式表显示了两种方法,前者用于父元素,后者用于 firstname 子元素。
<?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>
答案 1 :(得分:0)
问题是XSLT中的变量是不可变的。将它们视为常数。当你做了
<xsl:variable name="crm_fname" select="firstname" />
您在当前上下文中选择了“firstname”。我想这个代码在<xsl:template match='root'>
上下文中,所以你选择了“root / firstname”。没有这样的节点,因此结果如预期的那样是空的。
当您在for-each中调用变量时,您只需打印变量的内容,这一切都没有。
当你说变量是account/firstname
因为该节点存在时,它起了作用,但由于变量实际上是一个常量,它包含第一个匹配的内容,并且忽略了更改该值的任何其他尝试。 / p>
答案 2 :(得分:0)
在XSLT中,你必须忘记你所知道的任何程序范例。每当不合适时,您应该避免xsl:for-each
,而是编写单独的模板。
同样,在您的情况下不需要使用变量。也就是说,使用它们并非不可能,但正如@helderdarocha指出的那样,你必须意识到它们的不变性和上下文。
在您显示的样式表中,大多数变量可能都是空的,因为您选择的元素在该上下文中不存在。要选择元素而不管它们在层次结构中的哪个位置,请使用//
开始表达式。
<强>样式表强>
<?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>