【问题标题】:Including a variable value in a XSL select path is not working在 XSL 选择路径中包含变量值不起作用
【发布时间】:2020-02-20 08:43:47
【问题描述】:

我无法完全理解这一点。

所以我有这个外部 XML 数据文件:

<?xml version="1.0" encoding="UTF-8"?>
<Translations xmlns="http://www.publictalksoftware.co.uk/msa">
  <en>
    <Chairman>Chairman</Chairman>
    <Conductor>Conductor</Conductor>
    <Hospitality>Hospitality</Hospitality>
    <Prayer>Prayer</Prayer>
    <PublicTalk>Public Talk</PublicTalk>
    <Reader>Reader</Reader>
    <ServiceTalk>Service Talk</ServiceTalk>
    <Speaker>Speaker</Speaker>
    <Theme>Theme</Theme>
    <WTStudy>Watchtower Study</WTStudy>
  </en>
</Translations>

它在我的主 XSL 脚本中被引用如下:

<xsl:variable name="Translations" select="document('Workbook-S-140-Compact_2020_v2_Translations.XML')"/>

我可以像这样从这个 XML 文件中提取值:

<xsl:value-of select="$Translations/msa:Translations/msa:en/msa:ServiceTalk"/>

上面会拉出英文翻译。事情是这样的,在我的主要 XML 数据文件中,顶部有以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="Workbook-S-140-Compact_2020_v2.xsl"?>
<MeetingWorkBook>
    <Settings>
        <LanguageCode>en</LanguageCode>
        <Direction>ltr</Direction>
        <EditorMode>1</EditorMode>
        <ForeignGroupMode>0</ForeignGroupMode>
        <Now Day="20" Month="2" Year="2020"/>
    </Settings>

注意到LanguageCode 条目了吗?我想利用它,以便我的转换基于语言代码。所以我最初在我的 XSL 文件中添加了第二个变量:

  <xsl:variable name="LangCode">
    msa:<xsl:value-of select="//Settings//LanguageCode"/>
  </xsl:variable>

并像这样调整我的路径:

<xsl:value-of select="$Translations/msa:Translations/{$LangCode}/msa:ServiceTalk"/>

但它不喜欢它。我不知道如何将语言代码插入到路径查询中。我有很多这样的翻译行,所以如果可能的话,我正在寻找一个简单的解决方案。


我也尝试将变量保存为:

  <xsl:variable name="LangCode">
    <xsl:value-of select="//Settings//LanguageCode"/>
  </xsl:variable>

然后使用:

<xsl:value-of select="$Translations/msa:Translations/msa:{$LangCode}/msa:ServiceTalk"/>

还是失败了。

是否可以调整这条线:

<xsl:variable name="Translations" select="document('Workbook-S-140-Compact_2020_v2_Translations.XML')"/>

所以$Translations 指向Translations/langcode 节点?有意义吗?

【问题讨论】:

    标签: xml xslt-1.0


    【解决方案1】:

    您不能使用属性值模板来动态构造 XPath 表达式。

    但你可以在谓词中使用变量:

    <xsl:value-of select="$Translations/msa:Translations/msa:*[local-name() = $LangCode]/msa:ServiceTalk"/>
    

    【讨论】:

    • 太棒了!很有魅力。谢谢。
    • 太棒了! :) (下一次,请制作一个独立的示例,例如在 XSLT 小提琴上。当问题中的代码由不相关的三行代码组成时,很难弄清楚为什么某些事情不起作用,而忽略了许多重要的位。)
    【解决方案2】:

    为了扩展@Tomalak 的正确答案,您犯了几个错误:

    首先:

      <xsl:variable name="LangCode">
        msa:<xsl:value-of select="//Settings//LanguageCode"/>
      </xsl:variable>
    

    这里有几个问题。首先,“msa:”前面的空格是变量值的一部分,会导致匹配失败。其次,使用带有多个“//”运算符的路径非常昂贵。第三,您正在构造一个结果树片段,而构造一个字符串要简单得多:

    <xsl:variable name="LangCode" select="concat('msa:', //Settings/LanguageCode)"/>
    

    接下来,您误解了变量在 XPath 中的工作方式。变量代表值,而不是表达式文本的一部分(它不是像 shell 脚本那样的宏语言,而是像 Javascript 那样的表达式语言)。你的变量可以用在任何你可能在引号中使用字符串文字的地方,例如[contains(., 'fred')]可以变成contains(., $var)。它不能用于代替不允许使用字符串文字的表达式部分。用于文本替换的花括号仅在少数定义明确的上下文中起作用,它们从不用于替换表达式的一部分(至少,直到您在 XSLT 3.0 中使用阴影变量,但这是一个高级主题......)

    【讨论】:

    • 感谢分享。我将尝试这些改进。
    • 您的示例未编译。所以我尝试了&lt;xsl:variable name="LangCode" select="concat('msa:', //Settings/LanguageCode)"/&gt;,它确实可以编译。但后来我尝试了&lt;xsl:value-of select="$Translations/msa:Translations/*[local-name() = $LangCode]/msa:ScheduleHeading"/&gt; 并没有出现。
    • 在第一个实例中,我只需要在 concat 调用中添加右括号 )。但我不明白为什么随后从$Translations 中提取值的尝试失败了。
    • 我一定是做错了什么。但是公认的答案方法效果很好。
    猜你喜欢
    • 1970-01-01
    • 2015-07-12
    • 1970-01-01
    • 2014-01-20
    • 2014-04-14
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 2011-05-19
    相关资源
    最近更新 更多