Solved

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

Posted on 2014-09-03
6
172 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
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 
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

Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
Path of Workbook 3 76
c# code 19 71
MS Access XML API HTTP POST Call Object Send Not Working Correctly 15 51
.net and XML report from SCCM 5 20
Introduction In my previous article (http://www.experts-exchange.com/Microsoft/Development/MS-SQL-Server/SSIS/A_9150-Loading-XML-Using-SSIS.html) I showed you how the XML Source component can be used to load XML files into a SQL Server database, us…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
This Micro Tutorial will teach you how to censor certain areas of your screen. The example in this video will show a little boy's face being blurred. This will be demonstrated using Adobe Premiere Pro CS6.
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…

785 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