Expiring Today—Celebrate National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

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

Posted on 2014-09-03
6
Medium Priority
?
179 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 2
6 Comments
 
LVL 60

Assisted Solution

by:Geert Bormans
Geert Bormans earned 2000 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 2000 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 20

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
Application Discovery Service in AWS

In the era of the cloud, customers migrating away from their existing on-premise infrastructure. This requires lots of planning, strategies, and effort to identify their existing resources and determine how best to migrate.  Datacenter migrations happen in four phases -

 
LVL 60

Accepted Solution

by:
Geert Bormans earned 2000 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 20

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

Automating Terraform w Jenkins & AWS CodeCommit

How to configure Jenkins and CodeCommit to allow users to easily create and destroy infrastructure using Terraform code.

Question has a verified solution.

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

Browsing the questions asked to the Experts of this forum, you will be amazed to see how many times people are headaching about monster regular expressions (regex) to select that specific part of some HTML or XML file they want to extract. The examp…
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. 
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …
This tutorial will teach you the special effect of super speed similar to the fictional character Wally West aka "The Flash" After Shake : http://www.videocopilot.net/presets/after_shake/ All lightning effects with instructions : http://www.mediaf…
Suggested Courses

719 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