Solved

Use an XSLT variable to access an element in a specific part of an XML tree

Posted on 2014-09-03
6
174 Views
Last Modified: 2014-09-03
I'm using XSLT 1.0 (with lxml.etree and Python) to transform XML.  I can use "http://exslt.org/" extensions (common, strings and so on), but not XSLT 2.0.

The input XML has two main sections - a series of nested rules which have name="xxx" attributes, and a set of mappings that extend the definition of each "xxx".  The XML look like:
<process>
    <rules>
        <generalrule>
            <onerule name="xxx" startval="1" endval="5" maptype="full"/>
            <onerule name="yyy" startval="1" endval="5" maptype="full"/>
        </generalrule>
        <otherrule>
            <thisrule name="yyy" startval="1" endval="5" maptype="partial"/>
        </otherrule>
    </rules>
    <maps>
        <onemap name="xxx" attr1="8">
        <onemap name="yyy" attr1="4">
    </maps>
</process>

Open in new window

As you can see, the rule names can appear multiple times in the "rules" section, but will only appear once in the "maps" section.  The format is fixed - I'd love to change it but cannot.

I already have code in my templates which gets a map entry when parsing an entry from the main rules section, assuming that the element has a "name=" attribute:
<xsl:variable name="myattr1" select="/process/maps/onemap[@name = current()/@name]/@attr1" />

Open in new window

and I can then use the $myattr1 variable in the rest of the template.

What I am trying to do now is to get the attr1 attribute for an entry based on a variable name, not on being the current rule being parsed.  The variable value is actually being extracted from another attribute which has a comma-separated string of map names.

What do I need to replace the "[@name = current()/@name]" section with, to base the selection on the values of, say, the $first xsl variable?  Or do I need to do this a different way?

I have tried the simplistic ways - "[@name = $first]", "[@name = $first/@name]" and so on, and have tried using select="dyn:evaluate('/process/maps/onemap[@name = $first]/@name')"  (after adding xmlns:dyn="http://exslt.org/dynamic" to the stylesheet header).  They all either return nothing, or an evaluation error.  I keep thinking that there is something obvious that I am missing.
0
Comment
Question by:simon3270
  • 4
  • 2
6 Comments
 
LVL 60

Assisted Solution

by:Geert Bormans
Geert Bormans earned 500 total points
ID: 40301479
for that we have keys

keys put an index on elements in the document.
Fetching the element after is cheap

declare a key at the top level of your stylesheet
   <xsl:key name="map" match="maps/onemap" use="@name"/>

and use it like this
    <xsl:template match="onerule">
        <xsl:value-of select="key('map', @name)/@attr1"></xsl:value-of>
    </xsl:template>
0
 
LVL 60

Assisted Solution

by:Geert Bormans
Geert Bormans earned 500 total points
ID: 40301505
Ah OK, I think I missed one thing here.
Bottom line: use the key to not having to use variables

If the name of the attribute you need is in the $first variable

<xsl:value-of select="key('map', @name)/@*[name() = $first]"></xsl:value-of>

Try to avoid dynamic XPath at ALL cost
0
 
LVL 19

Author Comment

by:simon3270
ID: 40301539
It's not the name of the attribute that is is in $first, but the value of the "name=" in the maps/onemap elements, e.g. if $first contains "yyy", we want the value in
     /process/maps/onemap[@name = yyy]/@attr1
0
Space-Age Communications Transitions to DevOps

ViaSat, a global provider of satellite and wireless communications, securely connects businesses, governments, and organizations to the Internet. Learn how ViaSat’s Network Solutions Engineer, drove the transition from a traditional network support to a DevOps-centric model.

 
LVL 60

Accepted Solution

by:
Geert Bormans earned 500 total points
ID: 40301626
In the template you don't need a variable, but you can address the attribute in its context, as I showed in my first response
<xsl:value-of select="key('map', @name)/@attr1"></xsl:value-of>
or alternatively
<xsl:value-of select="key('map', $first)/@attr1"></xsl:value-of>
0
 
LVL 19

Author Closing Comment

by:simon3270
ID: 40302187
Geert, as always, masterful!  I'm still getting to grips with XSLT (it's not easy getting an old C hacker to use functional programming!), but your answers are a great teaching aid.  Many thanks.
0
 
LVL 60

Expert Comment

by:Geert Bormans
ID: 40302220
Welcome (and don't worry, you will be fine, I started off as a C-hacker as well :-)
0

Featured Post

Webinar: Aligning, Automating, Winning

Join Dan Russo, Senior Manager of Operations Intelligence, for an in-depth discussion on how Dealertrack, leading provider of integrated digital solutions for the automotive industry, transformed their DevOps processes to increase collaboration and move with greater velocity.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Word files to Wordpress Posts 2 65
Fixing Non-Standard characters in text 8 111
Convert XML to excel12book 5 33
PHP alternative to file_get_contents('php://input') 4 76
The Client Need Led Us to RSS I recently had an investment company ask me how they might notify their constituents about their newsworthy publications.  Probably you would think "Facebook" or "Twitter" but this is an interesting client.  Their cons…
Many times as a report developer I've been asked to display normalized data such as three rows with values Jack, Joe, and Bob as a single comma-separated string such as 'Jack, Joe, Bob', and vice versa.  Here's how to do it. 
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…
In a recent question (https://www.experts-exchange.com/questions/29004105/Run-AutoHotkey-script-directly-from-Notepad.html) here at Experts Exchange, a member asked how to run an AutoHotkey script (.AHK) directly from Notepad++ (aka NPP). This video…

830 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question