Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/xslt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
XSLT1.0无法在select的xsl:value中选择变量_Xslt_Xslt 1.0_Xsl Variable - Fatal编程技术网

XSLT1.0无法在select的xsl:value中选择变量

XSLT1.0无法在select的xsl:value中选择变量,xslt,xslt-1.0,xsl-variable,Xslt,Xslt 1.0,Xsl Variable,我尝试转换由多个源生成的一段XML。如果我将文本直接输入select语句的值,它将按预期工作。但一旦我尝试使用变量,它就不再有效了 如果我在xsl:for每个语句中使用变量,它也可以正常工作。这就是工作正常的XSL <xsl:variable name="crm_acc" select="account" /> <xsl:variable name="nav_acc" select="kontakt" /> <xsl:variable name="crm_fname

我尝试转换由多个源生成的一段XML。如果我将文本直接输入select语句的值,它将按预期工作。但一旦我尝试使用变量,它就不再有效了

如果我在xsl:for每个语句中使用变量,它也可以正常工作。这就是工作正常的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>

但是,如果我在select的xsl:value中使用变量,它就不能像下一个代码块中指定的那样工作。我尝试了很多组合,例如,只使用一个带有“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>

测试1
测试2
导航1
只有一次我得到一个结果,因为我在变量中指定了“account/firstname”。但是这样我总是只在每次迭代中得到第一个元素的值。在指定变量时,它似乎失去了上下文(处理器当前在“account”实体中,应该选择“firstname作为子节点”)

我读到select语句的值从XSLT1.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>

测试1
测试2
导航1

编辑:我应该提到的是,这些模板将/可以被修改,因此如果所有“变量”都在一个位置,那么就更容易了。可能是目标没有命名为“联系人”“但是,在整个文档中更改其他内容容易出错,而且是多余的。这些变量还用于XmlReader读取的另一个进程。我尽量减少配置和冗余的麻烦。

问题在于XSLT中的变量是不可变的。将它们视为常量。你什么时候做的

<xsl:variable name="crm_fname" select="firstname" />

您在当前上下文中选择了“firstname”。我假设该代码位于
上下文中,因此您选择了“root/firstname”。没有这样的节点,因此结果如预期的那样为空

当您在for each中调用变量时,您只是在打印变量的内容,而这并不是什么


当您说变量是account/firstname时,它起作用了,因为该节点存在,但由于该变量实际上是一个常量,它包含第一个匹配的内容,并且忽略了任何其他更改该值的尝试。

在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>

输出

<?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>

测试1
测试2
导航1

这里有两种可能的方法,您可能需要探索:一种是使用变量存储您可能希望调用的元素的所有可能的名称;另一个假设元素在其父元素中的位置是已知的,因此名称并不重要

下面的样式表显示了这两种方法,前者用于父元素,后者用于firstname子元素


账户
康塔克

我发布的示例非常简单,它将变得更加复杂,如果我可以使用变量,这将是一件好事,因为我必须在XSLT过程之外使用它们。(因此,如果我不必两次或多次指定这些内容,那就太好了)。我不明白的是为什么“联系人”->“名字”与“$contact”->“$firstname”不同(其中这些变量的内容是“contact”和“firstname”)。为什么在后一种情况下,这是一个不同的上下文?我应该提到的是,这些模板将/可以被修改,所以如果所有“变量”都在一个地方,这将更容易。可能是目标不是名为“联系人”,而是其他名称,在整个文档中更改它很容易出错,而且冗余我的答案解决了您的问题,就像一小时前一样。你应该避免在一个问题中包含太多的信息。因此,不要用更多的内容来扩展原始问题,而是在这个问题的解决方案的基础上提出一个新的问题。换句话说,研究我对初始问题的回答,在提出一个新问题之前使用这些见解来修改XSLT代码,从中找出新问题。现在还不清楚你所说的“联系人”->“名字”是什么意思,但这是你可以在一个新问题中解释的。这不是一个新问题,它仍然是一样的。也许我一开始还不够清楚。因此,我看不出你的回答目前如何回答我的问题(意图)。“联系人”->“名字”指的是范围。“firstname”在“contact”中执行。在xpath:contact/firstnameSo中,当我将文本直接写入select语句时,我处于for each(contact)上下文中,但是如果我使用变量,我处于根上下文中?是的,我知道XSL不是“正常”的编程语言