【问题标题】:Using Variable in Node Attribute在节点属性中使用变量
【发布时间】:2019-01-06 07:37:08
【问题描述】:

我正在编写一个 XSL 模板。我不知道如何为 XSL 文件中的自定义属性指定变量。

我正在 XSL 中尝试这段代码:

<xsl:variable name="var1" select="DEF"/>    
<frequency myAttr="ABC"+$var1 >    
     <xsl:value-of select="frequency"/>    
</frequency>  

预期结果是

<frequency myAttr="ABCDEF" >20</frequency>

我收到此错误:

无法使用提供的 XML/XSL 输入生成 XML 文档。 org.xml.sax.SAXParseException;行号:18;列号:24;元素类型“sourceId”必须后跟属性规范,“>”或“/>”

问题是我连接的方式是错误的。有什么帮助吗?

【问题讨论】:

  • 错误消息是指在某个文件的第 18 行有一个名为 sourceId 的未终止元素。您没有向我们展示任何名为sourceId 的元素,或任何>18 行的文件,因此很明显,此错误与您向我们展示的代码无关。但是,正如@michael.hor357k 所解释的那样,由于其他原因,您显示的代码是错误的。

标签: xpath xslt-1.0


【解决方案1】:

我想你的意思是:

<frequency myAttr="ABC{$var1}" >  

这会将文字字符串 "ABC"$var1 变量的内容连接起来 - 请参阅:Attribute Value Templates

请注意,您填充变量的方式表明源 XML 中有一个名为 DEF 的元素。只有当这个元素的字符串值为"DEF"时,才会得到预期的结果。

【讨论】:

    【解决方案2】:

    XSL 是一种 XML 格式的声明性语言。 XSLT 文件必须是格式正确的 XML。

    您尝试的内容看起来您具有命令式语言的编程知识,您可以在其中编写像"ABC" + $var1 这样的表达式。然而,这违反了 XSL 中的 XML 格式规则。元素遵循模式&lt;elementname attribute1="value1" attributeN="valueN"&gt;...&lt;/elementname&gt;。在您的代码中,您将 +$var1 放在 myAttr 属性的末尾,该属性以第二个引号结尾 - 这是无效的:&lt;frequency myAttr="ABC"+$var1 &gt;

    &lt;frequency myAttr="ABC+$var1"&gt; 会产生 ABC+$var1 的文字属性值,这不是您想要的。如果您尝试使用 XPath 语法作为属性值,concat('ABC', $var1) 作为来自&lt;frequency myAttr="concat('ABC', $var1)"&gt; 的字符串,也会发生这种情况。

    您可以使用 michael.hor257k 建议的属性值模板语法,这实质上意味着将 XPath 表达式包装在属性值字符串内的大括号中。

    另一种方法是不在代码中将元素写为文字,而是声明它:

    <xsl:variable name="var1" select="'DEF'"/>
    <xsl:element name="frequency">
      <xsl:attribute name="myAttr">
        <xsl:value-of select="concat('ABC', $var1)"/>
      </xsl:attribute>
    </xsl:element>
    

    请注意,我更正了变量定义:在select 属性中,如果应该是字符串,则必须将DEF 放在单引号中,例如select="'DEF'"。如果没有单引号,您可以定义变量以引用源 XML 中的 &lt;DEF&gt; 元素。

    &lt;xsl:value-of&gt;select 属性中,我使用XPath 函数concat() 连接字符串'ABC' 和变量$var1 的内容。此处不能使用属性值模板语法:select="'ABC{$var1}'" 将产生字符串ABC{$var1}

    上面例子的一个变体是使用&lt;xsl:text&gt;作为字符串ABC&lt;xsl:value-of&gt;来输出$var1的内容:

    <xsl:variable name="var1" select="'DEF'"/>
    <xsl:element name="frequency">
      <xsl:attribute name="myAttr">
        <xsl:text>ABC</xsl:text>
        <xsl:value-of select="$var1"/>
      </xsl:attribute>
    </xsl:element>
    

    所以有三种解决方案,一种是简洁的,一种是声明性的。你选择哪一个取决于你。打字最快的肯定是第一个:

    <xsl:variable name="var1" select="'DEF'"/>
    <frequency myAttr="ABC{$var1}">
      <xsl:value-of select="frequency"/>    
    </frequency>
    

    ...但您还应该了解实现相同结果的两种声明方式并了解它们的工作原理。

    【讨论】:

    • 其实还有第三种选择。在直接写入输出时,我当然不会使用 concat() - 所以如果 not 使用 AVT,我将使用两个单独的指令 - xsl:textxsl:value-of - 在 xsl:attribute 元素内.
    • 是的,将其添加为声明性示例的变体。我更喜欢concat(),因为它可以更快地扩展 IMO,但 YMMV 尤其是您使用的编辑器。我认为在性能方面使用什么并不重要。
    猜你喜欢
    • 1970-01-01
    • 2018-01-20
    • 1970-01-01
    • 1970-01-01
    • 2017-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多