I would like to have greater than and lesser than condition in xsl.
<?xml version="1.0" encoding="UTF-8"?>
<catalog>
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
<country>USA</country>
<company>Columbia</company>
<price>10.90</price>
<year>1985</year>
</cd>
<cd>
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
</cd>
</catalog>
xslt:
<?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>
<body>
<h2>My CD Collection</h2>
<table border="1">
<xsl:for-each select="catalog/cd">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<xsl:choose>
<xsl:when test="price > '9' and price < '10'">
<td bgcolor="#B22222">
<xsl:value-of select="artist"/>
</td>
</xsl:when>
</xsl:choose>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I tried
<xsl:when test="price > 9 and price < 10">.
But is not working.
Expected result: Display records which price is between 9 and 10.
Actual result : Nothing display
I added the xsl namespace, and its working fine.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<?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>
<body>
<h2>My CD Collection</h2>
<table border="1">
<xsl:for-each select="catalog/cd[price > '9' and price < '10']">
<tr>
<td>
<xsl:value-of select="title"/>
</td>
<td bgcolor="#B22222">
<xsl:value-of select="artist"/>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Output.
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr>
<td>Hide your heart</td>
<td bgcolor="#B22222">Bonnie Tyler</td>
</tr>
</table>
</body>
</html>
I think are you want following:-
<xsl:template match="catalog/cd">
<xsl:choose>
<xsl:when test="price > 9 and price < 10">
<xsl:copy-of select="*"/>
</xsl:when>
</xsl:choose>
</xsl:template>
OutPut:-
<title>Hide your heart</title>
<artist>Bonnie Tyler</artist>
<country>UK</country>
<company>CBS Records</company>
<price>9.90</price>
<year>1988</year>
Related
Maybe you can help me.
I don't know how to sum some table's cell "Year" which are grouped by "Title". I need that sum cell also would be merge as first cell "Title".
I used sum(), but it returs 0.
XMl Code:
<?xml version="1.0" encoding="UTF-8"?>
<LIST>
<Row>
<TITLE>Empire Burlesque</TITLE>
<YEAR>2001</YEAR>
<artist>Bob Dylan</artist>
<artist1>Bob Dylan1</artist1>
</Row>
<Row>
<TITLE>Empire Burlesque</TITLE>
<YEAR>2002</YEAR>
<artist>Bob Dylan</artist>
<artist1>Bob Dylanas</artist1>
</Row>
<Row>
<TITLE>Empire Burlesque</TITLE>
<YEAR>2003</YEAR>
<artist>Bonnie Tyler</artist>
<artist1>Bob Dylan</artist1>
</Row>
<Row>
<TITLE>Empire Burlesque</TITLE>
<YEAR>2004</YEAR>
<artist>Bonnie Tyler</artist>
<artist1>Bob Dylanas</artist1>
</Row>
<Row>
<TITLE>Empire Burlesque1</TITLE>
<YEAR>2005</YEAR>
<artist>Bonnie Tyler</artist>
<artist1>Bob Dylan</artist1>
</Row>
<Row>
<TITLE>Empire Burlesque1</TITLE>
<YEAR>2006</YEAR>
<artist>Bonnie Tyler</artist>
<artist1>Bob Dylanas</artist1>
</Row>
</LIST>
XSLT code:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:key name="cds" match="Row" use="TITLE" />
<xsl:template match="/">
<html>
<body>
<h2>My CD Collection</h2>
<table border="1">
<tr bgcolor="#9acd32">
<th>Title</th>
<th>Year</th>
<th>Artist</th>
<th>Artist1</th>
</tr>
<xsl:for-each select="LIST/Row[generate-id() = generate-id(key('cds', TITLE)[1])]" >
<tr>
<td>
<xsl:if test="key('cds', TITLE)[1]">
<xsl:attribute name="rowspan">
<xsl:value-of select="count(key('cds', TITLE))" />
</xsl:attribute>
</xsl:if>
<xsl:value-of select="TITLE"/>
</td>
<td>
<xsl:value-of select="YEAR"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
<td>
<xsl:value-of select="artist1"/>
</td>
</tr>
<xsl:for-each select="key('cds', TITLE)[position() > 1]">
<tr>
<td>
<xsl:value-of select="YEAR"/>
</td>
<td>
<xsl:value-of select="artist"/>
</td>
<td>
<xsl:value-of select="artist1"/>
</td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Now result is that:
Try sum(key('cds', TITLE)/YEAR) inside of the for-each.
I am trying to compare two xml using xsl:key, but not sure how to print unmatched keys. In this scenario I am keying b.xml and comparing with a.xml, but it does not print unmatched keys from b.xml.
a.xml
<root>
<metas>
<meta>
<name>x</name>
<value>0</value>
</meta>
<meta>
<name>y</name>
<value>1</value>
</meta>
<meta>
<name>z</name>
<value>1</value>
</meta>
</metas>
b.xml
<root>
<metas>
<info>
<name>a</name>
<value>0</value>
</info>
<info>
<name>y</name>
<value>1</value>
</info>
<info>
<name>z</name>
<value>1</value>
</info>
</metas>
Desired output:
Table
a.xml b.xml
name missing in a.xml a
value missing in a.xml 0
name x missing in b.xml
value 0 missing in b.xml
name y y
value 1 1
name z z
value 1 1
My xsl;
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:param name="uri" as="xs:string" select="'b.xml'"/>
<xsl:param name="b" as="document-node()" select="doc($uri)"/>
<xsl:key name="bCompare" match="root/metas/info" use="name"/>
<xsl:template match="/">
<html>
<head>
<title>Test</title>
</head>
<body>
<table>
<tr>
<td></td>
<th>a.xml</th>
<th>b.xml</th>
</tr>
<xsl:apply-templates/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="metas">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="meta">
<xsl:variable name="compare" select="key('bCompare', name, $b)"/>
<tr>
<th>Name</th>
<td>
<xsl:value-of select="name"/>
</td>
<td>
<xsl:value-of select="$compare/name"/>
<xsl:if test="empty($compare/name)">missing in b.xml</xsl:if>
</td>
</tr>
<tr>
<th>Value</th>
<td>
<xsl:value-of select="value"/>
</td>
<td>
<xsl:value-of select="$compare/value"/>
<xsl:if test="empty($compare/value)">missing in b.xml</xsl:if>
</td>
</tr>
</xsl:template>
You need to define a key for the other direction as well, i.e. <xsl:key name="aCompare" match="root/metas/meta" use="name"/>, then you need to make sure you process those elements of the second document with e.g. <xsl:apply-templates/><xsl:variable name="main-doc" select="/"/><xsl:apply-templates select="$b//info/meta[not(name = key('bCompare', $main-doc//meta/name, $main-doc))]"/> and then you need a template
<xsl:template match="info">
<xsl:variable name="compare" select="key('aCompare', name, $main-doc)"/>
<tr>
<th>Name</th>
<td>
<xsl:value-of select="$compare/name"/>
<xsl:if test="empty($compare/name)">missing in a.xml</xsl:if>
</td>
<td>
<xsl:value-of select="name"/>
</td>
</tr>
<tr>
<th>Value</th>
<td>
<xsl:value-of select="$compare/value"/>
<xsl:if test="empty($compare/value)">missing in a.xml</xsl:if>
</td>
<td>
<xsl:value-of select="value"/>
</td>
</tr>
</xsl:template>
This transformable HTML5:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<table border="1">
<caption>Complex Table</caption>
<tbody>
<tr>
<th>Title</th>
<th>Volume</th>
<th>Chapter</th>
<th>Stds.</th>
<th>Dept.</th>
</tr>
<tr>
<td rowspan="6">STEM</td>
<td rowspan="1">1</td>
<td rowspan="2">1</td>
<td>1 to 10</td>
<td rowspan="2">Biology</td>
</tr>
<tr>
<td rowspan="1">2</td>
<td>20 to 30</td>
</tr>
<tr>
<td rowspan="1">3</td>
<td rowspan="1">2</td>
<td>40 to 60</td>
<td rowspan="1">Chemistry</td>
</tr>
<tr>
<td>4</td>
<td>3</td>
<td>70 to 80</td>
<td>Physics</td>
</tr>
<tr>
<td rowspan="4">5</td>
<td rowspan="1">4</td>
<td>80 to 120</td>
<td rowspan="1">Math</td>
</tr>
<tr>
<td rowspan="1">5</td>
<td>120 to 135</td>
<td rowspan="1">Geometry</td>
</tr>
</tbody>
</table>
<table border="1">
<caption>Simpler Table</caption>
<tbody>
<tr>
<th>Title</th>
<th>Volume</th>
<th>Chapter</th>
<th>Stds.</th>
<th>Dept.</th>
</tr>
<tr>
<td colspan="1" rowspan="3">Kinesiology</td>
<td>1</td>
<td>1</td>
<td>A to C</td>
<td>Strength</td>
</tr>
<tr>
<td>2</td>
<td>2 to 3</td>
<td>D to H</td>
<td>Agility</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
<td>I to X</td>
<td>Flexibility</td>
</tr>
</tbody>
</table>
<table border="1">
<caption>Simplest Table</caption>
<tbody>
<tr>
<th>Title</th>
<th>Volume</th>
<th>Chapter</th>
<th>Stds.</th>
<th>Dept.</th>
</tr>
<tr>
<td>Skills</td>
<td>1</td>
<td>1</td>
<td>A to C</td>
<td>Keyboard</td>
</tr>
</tbody>
</table>
</body>
</html>
This desired output (if you view the rendered HTML, you can see the pattern of data wanted):
<?xml version="1.0" encoding="UTF-8"?>
<production>
<book title="STEM" volume="1"/>
<book title="STEM" volume="2"/>
<book title="STEM" volume="3"/>
<book title="STEM" volume="4"/>
<book title="STEM" volume="5"/>
<book title="Kinesiology" volume="1"/>
<book title="Kinesiology" volume="2"/>
<book title="Kinesiology" volume="3"/>
<book title="Skills" volume="1"/>
</production>
The not quite working transform:
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<catalog>
<xsl:apply-templates/>
</catalog>
</xsl:template>
<xsl:template match="text()"/>
<!-- multi-volume edition -->
<xsl:template match="table">
<xsl:variable name="title" select="descendant::td[1]"/>
<xsl:variable name="context-td" select="."/>
<!-- the following needs work -->
<xsl:for-each select="descendant::tr/td[1][matches(.,'\d+$')]">
<book>
<xsl:attribute name="title" select="$title"/>
<xsl:attribute name="volume" select="."/>
</book>
</xsl:for-each>
</xsl:template>
<!-- single-volume edition -->
<xsl:template match="table[count(descendant::tr) < 3]">
<book>
<xsl:attribute name="title" select="descendant::td[1]"/>
<xsl:attribute name="volume" select="descendant::tr[2]/td[2]"/>
</book>
</xsl:template>
</xsl:stylesheet>
The xpath in for-each needs work. I've tried various axis but haven't found one that works across all use cases.
Couldn't this be simply:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<catalog>
<xsl:apply-templates select="html/body/table"/>
</catalog>
</xsl:template>
<xsl:template match="table">
<xsl:variable name="title" select="tbody/tr[2]/td[1]"/>
<xsl:for-each select="tbody/tr[2]/td[2] | tbody/tr[position() > 2]/td[1]">
<book>
<xsl:attribute name="title" select="$title"/>
<xsl:attribute name="volume" select="."/>
</book>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Oops, I see there is a problem with volume 5 of STEM being listed twice - hold on...
No, I don't see a simple solution to this. I suspect you'd have to drill down into the table's structure, taking preceding rowspans into consideration - somewhat similar to:
Please suggest for XSLT code for Table rowspan and colspan issues
Edit:
Ok, I believe this should work:
XSLT 2.0
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<catalog>
<xsl:apply-templates select="html/body/table"/>
</catalog>
</xsl:template>
<xsl:template match="table">
<xsl:apply-templates select="tbody/tr[2]/td[2]">
<xsl:with-param name="title" select="tbody/tr[2]/td[1]" tunnel="yes"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="td">
<xsl:param name="title" tunnel="yes"/>
<book>
<xsl:attribute name="title" select="$title"/>
<xsl:attribute name="volume" select="."/>
</book>
<xsl:variable name="rowspan" select="if(#rowspan) then #rowspan else 1" />
<xsl:apply-templates select="parent::tr/following-sibling::tr[number($rowspan)]/td[1]"/>
</xsl:template>
</xsl:stylesheet>
Test, applied to a modified input in the form of:
http://xsltransform.net/94hvTz1/2
I tried it with grouping:
<xsl:stylesheet
version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<catalog>
<xsl:apply-templates select="//table"/>
</catalog>
</xsl:template>
<xsl:template match="table">
<xsl:for-each-group select="tbody/tr[position() gt 1]/td[1]" group-by="../../(tr[2]/td[2] | tr[position() gt 2]/td[1])">
<book title="{.}" volume="{current-grouping-key()}"/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
Would this help by any chance(little changes made to michael.hor257k's answer) :
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<catalog>
<xsl:apply-templates select="html/body/table"/>
</catalog>
</xsl:template>
<xsl:template match="table">
<xsl:variable name="title" select="tbody/tr[2]/td[1]"/>
<xsl:variable name="table-id" select="generate-id()"/>
<xsl:for-each select="tbody/tr[2]/td[2] | tbody/tr[position() > 2]/td[1]">
<xsl:variable name="curr-td" select="."/>
<xsl:if test="not(exists(following::tr[td[1][generate-id(../../..) = $table-id and . = $curr-td]]))">
<book>
<xsl:attribute name="title" select="$title"/>
<xsl:attribute name="volume" select="."/>
</book>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
basically i want to sort data by level and i'm getting an error. I'm a newbie to xslt. i tried the below code but not working.
here is my xml file.
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="XSLTEx1WT.xsl"?>
<Modules>
<module code="CSE2041">
<name>Web Technologies II</name>
<credit>3</credit>
<level>2</level>
</module>
<module code="CSE2031Y">
<name>Object Oriented Software Development</name>
<credit>6</credit>
<level>2</level>
</module>
<module code="CSE1041">
<name>Web Technologies I</name>
<credit>3</credit>
<level>1</level>
</module>
</Modules>
here is my xsl file
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:variable name="deptCredit" select="99"/>
<xsl:variable name="myBorder" select="1"/>
<xsl:template match="/">
<html>
<head>
<title>XSLT Exercise 1</title></head>
<body>
<table border="{$myBorder}">
<thead><tr><th>Module Name</th><th>No. of Credits</th><th>Level</th></tr></thead>
<tbody>
<xsl:apply-templates>
**<xsl:sort select="level" data-type="number"/>**
</xsl:apply-templates>
<tr><td colspan="3">Departmental credits needed: <xsl:value-of select="$deptCredit"/></td></tr>
<tr><td colspan="3">Percentage cleared: <strong> <xsl:value-of select="format-number(sum(//credit/text()) div $deptCredit,'##.##%')"/></strong>
</td></tr>
</tbody>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="module">
<xsl:apply-templates select="#code"/>
<tr><xsl:apply-templates select="*"/></tr>
</xsl:template>
<xsl:template match="name">
<xsl:call-template name="sjName"/>
</xsl:template>
<xsl:template match="#code">
<tr style="background-color:silver;">
<td colspan="3" style="text-align:center;">
<xsl:value-of select="."/>
</td>
</tr>
</xsl:template>
<xsl:template match="credit">
<td style="color:blue;"><strong><xsl:value-of select="text()"/></strong></td>
</xsl:template>
<xsl:template match="level">
<td style="color:blue;"><strong><xsl:value-of select="text()"/></strong></td>
</xsl:template>
<xsl:template name="sjName">
<xsl:choose>
<xsl:when test="contains(../#code,'Y')">
<td style="color:orange;font-weight:bold;"><xsl:value-of select="."/></td>
</xsl:when>
<xsl:otherwise>
<td style="color:lime;font-weight:bold;"><xsl:value-of select="."/></td>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
i have tried the above but its not working
You simply need to change this:
<xsl:apply-templates>
<xsl:sort select="level" data-type="number"/>
</xsl:apply-templates>
to this:
<xsl:apply-templates select="Modules/module">
<xsl:sort select="level" data-type="number"/>
</xsl:apply-templates>
Any help would be appreciated on this simple (I hope) problem. The xsl:for-each fails to find any elements after adding a namespace to this XML doc:
<?xml version="1.0" encoding="ISO-8859-1"?>
<?xml-stylesheet type="text/xsl" href="cdsort.xsl"?>
<catalog xmlns="http://www.mycompany.com/test" >
<cd>
<title>Empire Burlesque</title>
<artist>Bob Dylan</artist>
</cd>
<cd>
<title>Tupelo Honey</title>
<artist>Van Morrison</artist>
</cd>
</catalog>
Here is the XSL code:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"
xmlns:vv="http://www.mycompany.com/test"
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="vv:catalog/cd">
<tr>
<td><xsl:value-of select="title" /></td>
<td><xsl:value-of select="artist" /></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
You've set the default namespace for the whole document so the child elements in the xpaths also need a prefix:
<xsl:for-each select="vv:catalog/vv:cd">
<tr>
<td><xsl:value-of select="vv:title" /></td>
<td><xsl:value-of select="vv:artist" /></td>
</tr>
</xsl:for-each>