DannykPowell
DannykPowell

Reputation: 1227

Can I select in XPath based on a variable attribute?

I think this isn't possible but would like to have a definitive answer.

XML:

  <agentlang>French</agentlang>
  ...
  <books>
    <book>
      <title>My Book</title>
      <author>Me</author>
    </book>
    <book>
      <title>XPath 101</title>
      <author>You</author>
  </book>
  ...
 </books>
 .....
 <translations>
    <translation English="title" French="titre" German="Titel" />
    <translation English="author" French="auteur" German="Autor" />
 </translations>

then in the XSL there is a simple transform of the main books info, but I want the headers to be translated according to the translation xml- something like this will work:

<xsl:value-of select="//translation[@English='title']/@French"/>
<xsl:value-of select="//translation[@English='Author']/@French"/>

But I want to replace the attribute @French with the agentlang value from the XML

I'm using MSXML / XSLT 1.0

Is there any way this can be done?

Upvotes: 5

Views: 14681

Answers (2)

StuartLC
StuartLC

Reputation: 107237

Yes, you can use a local-name() to find an element or attribute with a given dynamic value. I've stored the lookup value in a xsl:variable:

<xsl:variable name="lang" select="//agentlang/text()" />
<xsl:value-of select="//translation[@English='title']/@*[local-name()=$lang]" />

If namespaces are involved, it is good practice to also include a check for namespace-uri()=..., as of course there may be two elements with the same name, but in different namespaces.

Edit

In hindsight, use of a variable may make the transform easier to read / maintain, but isn't essential - this can be done directly as well:

<xsl:value-of select="//translation[@English='title']/@*[local-name()=//agentlang]" />

Upvotes: 8

Jarod83
Jarod83

Reputation: 1

You could get the same result with a template

<xsl:template name="translate_english_to_local">
  <xsl:param name="text>

  <xsl:value-of select="//translation[@English=$text]/@*[local-name()=//agentlang]" />

</xsl:template>

Which would result into:

<xsl:call-template="translate_english_to_local">
    <xsl:with-param name="text">title</xsl:with-param>
</xsl:call-template>
  • Make the code easier to read
  • If you would change the translation library, you update the template and the rest will follow.

Upvotes: 0

Related Questions