Linking to an item in another node (XSLT) - html

I have an XML document with companies listed in it. I want to create a link with XSLT that contains the <link> child of the next node. Sorry if this is confusing..here is some sample XML of what i'm trying to obtain:
<portfolio>
<company>
<name>Dano Industries</name>
<link>dano.xml</link>
</company>
<company>
<name>Mike and Co.</name>
<link>mike.xml</link>
</company>
<company>
<name>Steve Inc.</name>
<link>steve.xml</link>
</company>
</portfolio>
I want two links, "BACK" and "NEXT". While currently on mike.xml, I want BACK to link to "dano.xml" and NEXT linked to "steve.xml"...etc..and have it dynamically change when on a different page based on the nodes around it. I want to do this because I may add and change the list as I go along, so I don't want to have to manually re-link everything.
How can I obtain this? Sorry I am new to XSLT, so please explain with solution if possible! Thanks in advance!

Based on your comments to Dimitre, I think what you're going to want to do is use the document() function to access your "master list" XML file.
What you are actually running the stylesheet on is the individual fragments (dano.xml, mike.xml, steve.xml), right?
I'll use "mike.xml" for an example. I don't know what the fragments look like so I had to make one up. You will need to be able to identify the correct <company> in the master list based on something in the fragment. In my example, the fragment has a <compName> element with the same value as the <name> element in the corresponding company in the master list XML.
Here is what the "master list" XML, "dano/mike/steve" XML, the stylesheet, and the resulting HTML look like:
master_list.xml:
<?xml version="1.0" encoding="UTF-8"?>
<portfolio>
<company>
<name>Dano Industries</name>
<link>dano.xml</link>
</company>
<company>
<name>Mike and Co.</name>
<link>mike.xml</link>
</company>
<company>
<name>Steve Inc.</name>
<link>steve.xml</link>
</company>
</portfolio>
dano.xml
<?xml version="1.0" encoding="UTF-8"?>
<fragment>
<compName>Dano Industries</compName>
<compInfo>Some info about Dano Industries</compInfo>
</fragment>
mike.xml:
<?xml version="1.0" encoding="UTF-8"?>
<fragment>
<compName>Mike and Co.</compName>
<compInfo>Some info about Mike and Co.</compInfo>
</fragment>
steve.xml
<?xml version="1.0" encoding="UTF-8"?>
<fragment>
<compName>Steve Inc.</compName>
<compInfo>Some info about Steve Inc.</compInfo>
</fragment>
stylesheet:
<?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" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="fragment">
<xsl:variable name="name" select="compName"/>
<xsl:variable name="previous-file">
<xsl:value-of select="document('master_list.xml')/portfolio/company[name=$name]/preceding-sibling::company[1]/link"/>
</xsl:variable>
<xsl:variable name="next-file">
<xsl:value-of select="document('master_list.xml')/portfolio/company[name=$name]/following-sibling::company[1]/link"/>
</xsl:variable>
<html>
<xsl:apply-templates/>
<p>
<xsl:if test="not($previous-file='')">
Back
</xsl:if>
<xsl:if test="not($previous-file='') and not($next-file='')">
<xsl:text> | </xsl:text>
</xsl:if>
<xsl:if test="not($next-file='')">
Next
</xsl:if>
</p>
</html>
</xsl:template>
<xsl:template match="compName">
<h1><xsl:apply-templates/></h1>
</xsl:template>
<xsl:template match="compInfo">
<p><xsl:apply-templates/></p>
</xsl:template>
</xsl:stylesheet>
HTML for Dano (dano.htm:)
<html>
<h1>Dano Industries</h1>
<p>Some info about Dano Industries</p>
<p>Next</p>
</html>
HTML for Mike (mike.htm:)
<html>
<h1>Mike and Co.</h1>
<p>Some info about Mike and Co.</p>
<p>Back | Next</p>
</html>
HTML for Steve (steve.htm:)
<html>
<h1>Steve Inc.</h1>
<p>Some info about Steve Inc.</p>
<p>Back</p>
</html>

This transformation:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<html>
<table border="1">
<xsl:apply-templates/>
</table>
</html>
</xsl:template>
<xsl:template match="company">
<xsl:variable name="vPrevious"
select="preceding-sibling::company[1]/link"/>
<xsl:variable name="vNext"
select="following-sibling::company[1]/link"/>
<tr>
<td>
<xsl:value-of select="name"/>
</td>
<td>
 
<xsl:if test="$vPrevious">
Back
</xsl:if>
</td>
<td>
 
<xsl:if test="$vNext">
Next
</xsl:if>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<portfolio>
<company>
<name>Dano Industries</name>
<link>dano.xml</link>
</company>
<company>
<name>Mike and Co.</name>
<link>mike.xml</link>
</company>
<company>
<name>Steve Inc.</name>
<link>steve.xml</link>
</company>
</portfolio>
produces the desired HTML table with "Back" and "Next" links:
<html>
<table border="1">
<tr>
<td>
Dano Industries
</td>
<td> </td>
<td>
Next
</td>
</tr>
<tr>
<td>
Mike and Co.
</td>
<td>
Back
</td>
<td>
Next
</td>
</tr>
<tr>
<td>
Steve Inc.
</td>
<td>
Back
</td>
<td> </td>
</tr>
</table>
</html>

Related

Browsers don't parse stylesheet properly

I have an XML File:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet hred="remakes.xsl" type="text/xsl" ?>
<remakes>
<remake>
<rtitle>Pygmalion</rtitle>
<ryear>1938</ryear>
<fraction>0.5</fraction>
<stitle>Pygmalion</stitle>
<syear>1937</syear>
</remake>...
and I have created a stylesheet:
?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/remakes">
<html>
<body>
<table border="1">
<tr>
<th>rtitle<</th>
<th>fraction<</th>
<th>stitle<</th>
<th>syear<</th>
</tr>
<xsl:for-each select="remake">
<xsl:value-of select="rtitle"/></td>
<xsl:value-of select="fraction"/></td>
<xsl:value-of select="stitle"/></td>
<xsl:value-of select="syear"/></td>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
But browsers don't parse it so instead of a table there is chaos. Is there a mistake in the code?
There are a number of problems with your stylesheet, although they could always be typos with your question, but as there are too many to mention in comments, they are as follows:
The namespace prefix xsl has not been bound. You should type xmlns:xsl="..."
There is a < symbol in each table header <th>rtitle<</th>. If you really wanted this, you should write it as <th>rtitle<</th>, but more likely it should just be <th>rtitle</th>
You have a closing <\td> for each row, but no opening <td> tag.
You also really need to wrap those <td> in a <tr> tag for it to be rendered properly.
Try this XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/remakes">
<html>
<body>
<table border="1">
<tr>
<th>rtitle</th>
<th>fraction</th>
<th>stitle</th>
<th>syear</th>
</tr>
<xsl:for-each select="remake">
<tr>
<td><xsl:value-of select="rtitle"/></td>
<td><xsl:value-of select="fraction"/></td>
<td><xsl:value-of select="stitle"/></td>
<td><xsl:value-of select="syear"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

XSLT position() function not working as expected in Two Step View

While trying to implement the pattern "Two Step View" as described by Martin Fowler, I had some problems getting the alternate-row colouring of the HTML table to work. This uses the XSLT position() function. You can see the XSLT template for table/row below. However, in the output, the bgcolor attribute of the tr element is always "linen", indicating that the value of position() is not changing as we iterate over table/row elements. Why would this be?
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="screen">
<html>
<body bgcolor="white">
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="title">
<h1>
<xsl:apply-templates/>
</h1>
</xsl:template>
<xsl:template match="field">
<p><b><xsl:value-of select="#label"/>: </b><xsl:apply-templates/></p>
</xsl:template>
<xsl:template match="table">
<table><xsl:apply-templates/></table>
</xsl:template>
<xsl:template match="table/row">
<xsl:variable name="bgcolor">
<xsl:choose>
<xsl:when test="(position() mod 2) = 0">linen</xsl:when>
<xsl:otherwise>white</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<tr bgcolor="{$bgcolor}"><xsl:apply-templates/></tr>
</xsl:template>
<xsl:template match="table/row/cell">
<td><xsl:apply-templates/></td>
</xsl:template>
</xsl:stylesheet>
Input XML:
<?xml version="1.0"?>
<screen>
<title>Dissociation</title>
<field label="Artist">Dillinger Escape Plan</field>
<table>
<row>
<cell>Limerent Death</cell>
<cell>4:06</cell>
</row>
<row>
<cell>Symptom Of Terminal Illness</cell>
<cell>4:03</cell>
</row>
<row>
<cell>Wanting Not So Much To As To</cell>
<cell>5:23</cell>
</row>
</table>
</screen>
Output HTML:
<html><body bgcolor="white">
<h1>Dissociation</h1>
<p><b>Artist: </b>Dillinger Escape Plan</p>
<table>
<tr bgcolor="linen">
<td>Limerent Death</td>
<td>4:06</td>
</tr>
<tr bgcolor="linen">
<td>Symptom Of Terminal Illness</td>
<td>4:03</td>
</tr>
<tr bgcolor="linen">
<td>Wanting Not So Much To As To</td>
<td>5:23</td>
</tr>
</table>
</body></html>
Change <table><xsl:apply-templates/></table> to <table><xsl:apply-templates select="row"/></table> or use <xsl:strip-space elements="*"/> or at least <xsl:strip-space elements="table"/>. Currently you are processing all child nodes, including white space text nodes, that way your attempt using position() fails.

XSLT: Getting attribute Value in a nested when

Hi,
I am trying to extract attribute value from a xml using xslt. The snippets are below.
XSlt to extract the data from attributes . Used when loop to extract attribute data.
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<tr>
<xsl:choose>
<xsl:when test="//catalog/cd/title/artist/country/item/#id='mod1'">
<td>asdfg</td>
<xsl:choose>
<xsl:when test="//catalog/cd/title/artist/country/item/item/#id='up1'">
<td>
<xsl:value-of select="//catalog/cd/title/artist/country/item/item/#value" />
</td>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</tr>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
XML data to be parsed.
<?xml version="1.0" encoding="utf-8"?>
<!-- Edited by XMLSpy -->
<catalog>
<cd>
<title>
<artist>
<country>
<item type="layer" id="mod" title="Mod" result="pass">
<item type="measure" id="up" title="Up" value="10" unit="dBm" />
<item type="measure" id="down" title="Down" value="9.6" unit="dBm" />
</item>
<item type="layer" id="mod1" title="Mod1" result="pass">
<item type="measure" id="up1" title="Up" value="100" unit="dBm" />
<item type="measure" id="down1" title="Down" value="9.60" unit="dBm" />
</item>
</country>
</artist>
</title>
</cd>
</catalog>
Expected Output and Actual Output Below:
Expected output:
My CD Collection
Title | Artist
asdfg | 100
Actual Output:
My CD Collection
Title | Artist
asdfg | 10
Would be really thankful for a solution. Thanks in advance.
Basically, the logic in your XSLT is saying:
If any item id is mod1
Then show a table cell with the value "asdfg"
And if any item's item ID is up1
Then show the value attribute of the first item's item in the document
To accomplish what you are trying to do, you can do this:
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<tr>
<xsl:variable name="mod1"
select="//catalog/cd/title/artist/country/item[#id = 'mod1']" />
<xsl:if test="$mod1">
<td>asdfg</td>
<xsl:variable name="up1" select="$mod1/item[#id = 'up1']" />
<xsl:if test="$up1">
<td>
<xsl:value-of select="$up1/#value" />
</td>
</xsl:if>
</xsl:if>
</tr>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
As XSLT goes, this isn't very representative of what well-written XSLT looks like, but I am putting it here as an example because I assume that this is not your ultimate goal and that you are trying this as a step toward your final goal.
For the next step, I suggest opening up a new question.

online xml to html parser

I am looking for a online program that parses any xml to html. For instance, if I have the following xml layout
<users>
<user>
</name>john</name>
<pictures>
<pic1>URL of picture1.png</pic1>
<pic2>URL of picture2.png</pic2>
</pictures>
</user>
<user>
</name>mary</name>
<pictures>
<pic1>URL of picture1.png</pic1>
<pic2>URL of picture2.png</pic2>
</pictures>
</user>
</users>
it can create an html page displaying the content of the nodes and give some minimal formatting for easy reading. Any such tool?
Edit: I just gave an example, I want a generic tool that can parse any xml without knowing its structure beforehand.
One way to tackle this would be to apply an XSLT transformation.
You'd need to create an XSL stylesheet, something like...
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<head>
<title>Contacts</title>
</head>
<body>
<xsl:for-each select="//user">
<h2><xsl:value-of select="name" /></h2>
<p><xsl:value-of select="pictures/pic1" /></p>
<p><xsl:value-of select="pictures/pic2" /></p>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Then link to it at the top of your xml file. In the example below the second line links to the stylesheet named 'myStyleSheet.xsl'.
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="myStyleSheet.xsl"?>
<users>
<user>
<name>john</name>
<pictures>
<pic1>URL of picture1.png</pic1>
<pic2>URL of picture2.png</pic2>
</pictures>
</user>
<user>
<name>mary</name>
<pictures>
<pic1>URL of picture1.png</pic1>
<pic2>URL of picture2.png</pic2>
</pictures>
</user>
</users>
You could try this.
http://www.w3schools.com/xsl/tryxslt.asp?xmlfile=cdcatalog&xsltfile=cdcatalog_choose
<?xml version="1.0" encoding="ISO-8859-1"?>
<!-- Edited by XMLSpy® -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Artist</th>
</tr>
<xsl:for-each select="catalog/cd">
<tr>
<td><xsl:value-of select="title"/></td>
<xsl:choose>
<xsl:when test="price > 10">
<td bgcolor="#ff00ff">
<xsl:value-of select="artist"/>
</td>
</xsl:when>
<xsl:otherwise>
<td><xsl:value-of select="artist"/></td>
</xsl:otherwise>
</xsl:choose>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>

using XSL Transform XML data and their child elements in tabular format HTML

This is my test XML in this XML i have child element: INSTRUMENT and sub child element: INSTRUMENT/issuer and could be so on ...
5002199
10001
686184SE3
<INSTRUMENT>
<type>FI</type>
<issuer>
<FICode>123456</FICode>
<name>Test</name>
<city>SF</city>
<state>CA</state>
</issuer>
<issueDate>2011-06-22-05:00</issueDate>
<maturityDate>2016-06-22-05:00</maturityDate>
<firstCouponDate>2011-07-22-05:00</firstCouponDate>
<lastCouponDate>2016-05-22-05:00</lastCouponDate>
<couponRate>2.0</couponRate>
<paymentFrequency>12</paymentFrequency>
<callSchedule>
<notice>15</notice>
<timing>0</timing>
<call id="1">
<startDate>2011-12-22-05:00</startDate>
<type>2</type>
<freq>M</freq>
</call>
</callSchedule>
</INSTRUMENT>
<Commision>7.0</Commision>
<price>100.0</price>
I want to display this data in HTML tabular form, and run time the xml element could be any thing, so i can't hard code the element or subelement name
i was trying follwinf XSL
<xsl:template match="/">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="*">
<table border="1" width="1000">
<tr>
<td class="section_head">Key</td>
<td class="section_head">Value</td>
</tr>
<xsl:for-each select="*" >
<tr>
<td>
<xsl:value-of select="name(.)" />
</td>
<td>
<xsl:value-of select="." />
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
the HTM Child INSTRUMENT and issuer and callSchedule is comming in tabular form
is there any way i can iterate XSL recursivley to create HTML child table for XML child elements ?
Key
Value
ID
5002199
Code
10001
cusip
686184SE3
INSTRUMENT
FI 123456 Test SF CA 2011-06-22-05:00 2016-06-22-05:00 2011-07-22-05:00 2016-05-22-05:00 2.0 12 15 0 2011-12-22-05:00 100.0 2 M 2012-01-22-05:00 100.0 2012-02-22-05:00 100
Commision
7.0
price
100.0
alloc
100
I am not exactly sure what you are after here. It looks like you want to convert the nodes into name/value pairs and nest the html tables according to the XML hierarchy. Here is a bit of recursion that addresses the problem of not knowing the node names at runtime. Hopefully it well help you get started with this. If it is not what you are looking for you can use it to clarify your question:
<?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" indent="yes"/>
<xsl:template match="/">
<html>
<table>
<xsl:apply-templates/>
</table>
</html>
</xsl:template>
<xsl:template match="*[count(*) = 0]">
<tr>
<td>
<xsl:value-of select="name(.)" />
</td>
<td>
<xsl:value-of select="." />
</td>
</tr>
</xsl:template>
<xsl:template match="*[count(*) > 0]">
<tr>
<td>
<xsl:value-of select="name(.)" />
</td>
<td>
<table>
<xsl:apply-templates/>
</table>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>