Solved

"Back references" in XML / XSLT

Posted on 2003-11-17
6
324 Views
Last Modified: 2013-11-19
I am trying to write a XSLT transform to output a list of URLs. The URLs are shared folders on particular servers. The XML fragment containing the URLs appears below. I would like a neat way to combine the attribute called "name" with the href attribute in the output in such a way that I do not have to repeat the actual name of the server.

<machine name="MYSERVER">
<links>
<a href="file://MYSERVER/Share1">First Shared Folder</a>
<a href="file://MYSERVER/Share2">Second Shared Folder</a>
</links>
</machine>

Note the redundancy in the repeated string "MYSERVER". Perhaps the solution hinges on rewriting the <a> tags to read <a description="First Shared Folder">file://<machineName/>/Share1</a> and somehow replacing the machineName element in the output... but I can't get this to work!

Any ideas?
0
Comment
Question by:freshqwa
  • 4
  • 2
6 Comments
 
LVL 11

Expert Comment

by:petiex
ID: 9768284
So, you want the xsl to make it possible to have a simpler xml? With an xml that looks like this:

<machine name="MYSERVER">
<links>
<link foldername=Share1>First Shared Folder</link>
<link foldername=Share2>Second Shared Folder</link>
</links>
</machine>

You could generate a bulleted list of links for each machine with an xsl like this:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<xsl:apply-templates select="machine"/>
</xsl:template>

<xsl:template match="machine">
<xsl:variable name="servername"  select="@name"/>
<xsl:value-of select="@name">
<ul>
<xsl:for-each select="link">
<li><a href="{concat('file://', $servername, @foldername)}"><xsl:value-of select="."></a></li>
</xsl:for-each>
</ul>
</xsl:template>

</xsl:stylesheet>
0
 

Author Comment

by:freshqwa
ID: 9769903
Thanks for the suggestion... it's not quite what I am after but may be the only way to do it... There are actually a couple of places in my XML schema where I would like to be able to easily refer to an attribute of a parent node (in fact up to several levels back up the node tree).

I have been unable to find a syntax like the filesystem "dot dot" convention that will take my context back up a level. For example, I could use the following:

<machine name="MYSERVER">
<links>
<a description="First Shared Folder">file://<replaceMe path="../../@name"/>/Share1</a>
</links>
</machine>

If I could write a template for all "replaceMe" elements that would return the node refered to by the "path" attribute as a string. As I say, there are a few more instances where I would like to write "self referential" XML (ie repeating previous values in several places). I would rather not have to pass the value as a parameter all the way down through my templates to where it is needed, but this may be the only way.

Agh, is it just me or is XSL the most frustrating thing to use!
0
 
LVL 11

Expert Comment

by:petiex
ID: 9775061
Possibly the current() function is what you need. It refers to the initial context of a template, which is useful within for-each loops.

So, in the stylesheet of my previous post, you could use current()/@name in place of that $servername variable to the same effect. I've also fixed a couple or three fatal bugs in the stylesheet of my previous post:

XML:
<machine name="MYSERVER">
  <links>
     <link foldername=Share1>First Shared Folder</link>
     <link foldername=Share2>Second Shared Folder</link>
   </links>
</machine

XSL:
<?xml version="1.0" encoding="UTF-8"?>
 <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
   <xsl:output method="html"/>
   <xsl:template match="/">
     <html><body>
       <xsl:apply-templates select="machine"/>
     </body></html>
  </xsl:template>

  <xsl:template match="machine">
     <xsl:value-of select="@name"/>
     <ul>
         <xsl:for-each select="links/link">
             <li>
                 <a href="{concat('file://', current()/@name, @foldername)}">
                      <xsl:value-of select="."/>
                 </a>
             </li>
         </xsl:for-each>
    </ul>
  </xsl:template>

 </xsl:stylesheet>


OUTPUT:
<html>
<body>MYSERVER<ul>
<li>
<a href="file://Share1">First Shared Folder</a>
</li>
<li>
<a href="file://Share2">Second Shared Folder</a>
</li>
</ul>
</body>
</html>

If you think XSL is the most frustrating thing to use, stay away from XSL-FO. Bad mojo, that XSL-FO. :)
0
How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

 
LVL 11

Expert Comment

by:petiex
ID: 9775119
Uh, no, sorry that's not right at all. It turns out the current() function is only useful within a predicate.
0
 
LVL 11

Accepted Solution

by:
petiex earned 100 total points
ID: 9775249
So, like you said, you need to use the dot dot syntax. So, here's the best I can do:

XML:

<machine name="MYSERVER">
  <links>
     <link foldername=Share1>First Shared Folder</link>
     <link foldername=Share2>Second Shared Folder</link>
   </links>
</machine>

XSL:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<html><body>
<xsl:apply-templates select="machine"/>
</body></html>
</xsl:template>

<xsl:template match="machine">
<xsl:value-of select="@name"/>
<ul>
<xsl:for-each select="links/link">
<li><a href="{concat('file://', ../../@name, '/', @foldername)}"><xsl:value-of select="."/></a></li>
</xsl:for-each>
</ul>
</xsl:template>

</xsl:stylesheet>

OUTPUT:
<html>
<body>MYSERVER<ul>
<li>
<a href="file://MYSERVER/Share1">First Shared Folder</a>
</li>
<li>
<a href="file://MYSERVER/Share2">Second Shared Folder</a>
</li>
</ul>
</body>
</html>
0
 

Author Comment

by:freshqwa
ID: 9777233
Thanks for your time & effort, I can work with this solution... Cheers!
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
ColdFusion Rereplace 3 62
Removing information on Duplicate XML Nodes 24 66
PHP and Soap 3 27
XML filtering Windows Event Viewer 10 38
Shoutout to Emily Plummer (http://www.experts-exchange.com/members/eplummer26.html) for giving me this article! She did most of it, I just finished it up and posted it for her :)    Introduction In a previous article (http://www.experts-exchang…
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.
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
The viewer will receive an overview of the basics of CSS showing inline styles. In the head tags set up your style tags: (CODE) Reference the nav tag and set your properties.: (CODE) Set the reference for the UL element and styles for it to ensu…

707 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now