0

我尝试转换由多个来源生成的一段 XML。如果我将文本直接输入到 value-of select 语句中,它会按预期工作。但是一旦我尝试使用变量,它就不再起作用了。

如果我在 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>

只有一次我得到结果,因为我在变量中指定了“帐户/名字”。但是这样我总是只在每次迭代中获得第一个元素的值。似乎在指定变量时它失去了上下文(处理器当前位于“帐户”实体内,应该选择“名字作为子节点”)。

我读到 value-of select 语句从 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 读取的另一个进程。我尽量减少配置和冗余的麻烦。

4

3 回答 3

1

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

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

<?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>
于 2014-02-06T10:20:03.677 回答
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>
于 2014-02-05T15:01:14.937 回答
0

问题是 XSLT 中的变量是不可变的。将它们视为常数。当你做了

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

您在当前上下文中选择了“名字” 。我想该代码在<xsl:template match='root'>上下文中,因此您选择了“root/firstname”。没有这样的节点,所以结果如预期的那样是空的。

当您在 for-each 中调用变量时,您只是打印变量的内容,这没什么。

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

于 2014-02-05T14:43:38.657 回答