1

Following my previous post : XSLT take first element that can be mapped among list of predefined mappings

Is there a way to evaluate a variable, in a xsl:value-of, whose name is coming from the evaluation of XPATH ?

The original XML :

<sectors type="array">
   <sector>industry</sector>
   <sector>e-commerce</sector>
   <sector>logistique</sector>
<sectors>

This is my XSLT (thanks to https://stackoverflow.com/a/73040079/10767428) :

<xsl:import href="./sector.xslt"/>

<s:sector source="metallurgy" target="$sector_industry_materials" />
<s:sector source="accounting" target="$sector_audit_accounting" />
<s:sector source="logistics" target="$sector_service_logistics" />
<s:sector source="mass-distribution" target="$sector_distribution_mass_retail" />

<xsl:template match="sectors">
    <sectorIdentifier>
        <xsl:variable name="sector" select="sector[. = document('')/*/s:sector/@source][1]"/>
        <xsl:choose>
            <xsl:when test="$sector">
                <xsl:variable name="target" select="document('')/*/s:sector[@source=$sector]/@target"/>
                <xsl:value-of select="$target" />
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="$sector_other"/>
            </xsl:otherwise>
        </xsl:choose>
    </sectorIdentifier>
</xsl:template>

Here, the value of $target are either the strings : $sector_industry_materials, $sector_audit_accounting, $sector_service_logistics, $sector_distribution_mass_retail or $sector_other.

I want those strings to be evaluated against the following other XSLT, from another file, and imported in current file :

sector.xslt :

<?xml version="1.0" ?>
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">  
  <xsl:variable name="sector_industry_materials" >401</xsl:variable>
  <xsl:variable name="sector_audit_accounting" >374</xsl:variable>
  <xsl:variable name="sector_service_logistics" >422</xsl:variable>
  <xsl:variable name="sector_distribution_mass_retail" >387</xsl:variable>
  <xsl:variable name="sector_other" >456</xsl:variable>
</xsl:stylesheet>

So the final output, in case the $target value was the string $sector_industry_materials, must be :

<sectorIdentifier>401</sectorIdentifier>

But for now, all I get is :

<sectorIdentifier>$sector_distribution_mass_retail</sectorIdentifier>

The thing is that with $sector_other, which is hard-coded, everything works fine, and I get :

<sectorIdentifier>456</sectorIdentifier>

SO the problem must be that name of the variables are dynamic.

Thank you

5
  • 1
    Dynamic XPath evaluation exists as an optional feature with xsl:evaluate only in XSLT 3.0 (Saxon 10 HE and later, Saxon 9.8 PE/EE and later, Saxon-JS 2) or as processor specific, proprietary extension in earlier versions. Which XSLT 1.0 processor exactly do you use? Commented Jul 20, 2022 at 14:16
  • 2
    This is very confusing. Could you not eliminate the middleman and map industry directly to 401, accounting to 374 and so on? This map could be hard-coded into your stylesheet or - if you prefer - it could be stored in an external XML document. Such document does not need to be an XSLT stylesheet; in fact, making it so only complicates things. Commented Jul 20, 2022 at 15:47
  • 1
    At first sight this seems to be a very complicated way of achieving something very simple. But you haven't explained what you're trying to achieve, and it's really hard to reverse engineer the requirements from the code. Commented Jul 21, 2022 at 12:20
  • @michael.hor257k I agree that this seems complicated, but we need to have this middleware for code generation. But I will check if there is a way to have a direct mapping between metallurgy and 401 in the XML file itself, instead of going through the process of finding first sector_industry_materials. Thank you for your time. Commented Jul 21, 2022 at 13:08
  • Even with 2 maps, it should be quite simple to find the first sector that has an entry in map A using key('sector', $mapA/key)[1] and then lookup the corresponding value in map B using key('mapB', $foundValue). At no point should there be a need to evaluate a string as an XPath expression. Commented Jul 21, 2022 at 13:47

1 Answer 1

1

You could use the same technique and drill into the imported sector.xslt as an XML doc, selecting the value with XPath:

<xsl:when test="$sector">
  <xsl:variable name="target" select="document('')/*/s:sector[@source=$sector]/@target"/>
  <!-- <xsl:value-of select="$target" /> -->
  <xsl:value-of select="document('sector.xslt')/xsl:stylesheet/xsl:variable[contains($target, @name)]"/>
</xsl:when>

It would be a little more straightforward if you changed the s:sector/@target values not to have $ for variable name references, and just had the value to match the sector.xslt xsl:variable/@name.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, this works as expected. I did not think of using the XSLT sheet as a regular XML file.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.