I am facing issues while displaying the xml in html table using xsl.
1. The html view is repeating with the below xsl and
2. unable to differentiate sub elements with the same name (Eg: name tag in the below xml).
The xml is having different kinds of information in different nodes as follows.
<employee>
<address>
<street>street1</street>
<city>city1</city>
<pincode>123456</pincode>
</address>
<personalinfo>
<name>testname1</name>
<phone>999999999</phone>
<dob>23-09-34</dob>
</personalinfo>
<remarks>
<education>
<name>testname2</name>
<college>college1</college>
<gpa>7.5</gpa>
</education>
</remarks>
</employee>
and Here is my 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="employee">
<html>
<body>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:template match="address|personalinfo|remarks">
<table width="630">
<tr>
<td>Name</td>
<td>College</td>
<td>City</td>
</tr>
<tr>
<td><xsl:value-of select="//name"/></td>
<td><xsl:value-of select="//college"/></td>
<td><xsl:value-of select="//city"/></td>
</tr>
</table>
<span><br/>
</span>
</xsl:template>
</xsl:stylesheet>
Please help me in this regard. Thank you.
Judging from your table structure, you want to move the table header up to the template matching the root node, and then get the corresponding detail of each employee using a relative (and explicit) path:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/">
<html>
<body>
<table>
<tr>
<th>Name</th>
<th>College</th>
<th>City</th>
</tr>
<xsl:apply-templates/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="employee">
<tr>
<td>
<xsl:value-of select="personalinfo/name"/>
</td>
<td>
<xsl:value-of select="remarks/education/college"/>
</td>
<td>
<xsl:value-of select="address/city"/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
The expression //name selects all the name elements anywhere in the document. That's not you want: you want the name element within the personalInfo or remarks that you are currently processing: that's select="name" for an immediate child, or select=".//name" for a descendant at any depth.
It seems odd to use the same template rule to process three elements (address|personalinfo|remarks) that have very different structure.
Related
I am trying to create some reusable templates while developing a html page for xml with xsl. But when I include the other xsl's, the main xsl template is getting overridden instead of adding it to it. please suggest.
Here is my xml,
<employee>
<address>
<street>street1</street>
<city>city1</city>
<doornumber>1-23</doornumber>
<pincode>123456</pincode>
</address>
<personalinfo>
<name>testname1</name>
<phone>999999999</phone>
<dob>23-09-34</dob>
</personalinfo>
<remarks>
<education>
<name>testname2</name>
<college>college1</college>
<gpa>7.5</gpa>
</education>
</remarks>
<data>
<name>data1</name>
</data>
<data>
<name>data2</name>
</data>
<data>
<name>data3</name>
</data>
<data>
<name>data4</name>
</data>
<data>
<name>data5</name>
</data>
</employee>
Here is my main xsl,
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="/">
<html>
<body>
<table>
<tr>
<th>Name</th>
<th>College</th>
<th>City</th>
</tr>
<xsl:apply-templates/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="employee">
<tr>
<td>
<xsl:value-of select="personalinfo/name"/>
</td>
<td>
<xsl:value-of select="remarks/education/college"/>
</td>
<td>
<xsl:value-of select="address/city"/>
</td>
</tr>
</xsl:template>
<!-- <xsl:include href="test_include1.xsl" /> -->
<!-- <xsl:include href="test_include2.xsl" /> -->
</xsl:stylesheet>
Here is my test_include1.xsl,
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="employee">
<table><tr>
<th>data names</th></tr>
<xsl:for-each select="data">
<tr>
<td>
<xsl:value-of select="name"/>
</td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Here is my test_include2.xsl,
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:template match="employee">
<table><tr>
<th>Name</th>
<th>College</th></tr>
<tr>
<td>
<xsl:value-of select="personalinfo/name"/>
</td>
<td>
<xsl:value-of select="remarks/education/college"/>
</td>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
I am trying to modularize the same xml data in different templates so that I can reuse the same templates in other stylesheets. Please suggest how I can acheive this. Thank you.
Here is the expected result,
<html><body>
<table>
<tr>
<th>Name</th>
<th>College</th>
<th>City</th>
</tr>
<tr>
<td>testname1</td>
<td>college1</td>
<td>city1</td>
</tr>
</table>
<table>
<tr><th>data names</th></tr>
<tr><td>data1</td></tr>
<tr><td>data2</td></tr>
<tr><td>data3</td></tr>
<tr><td>data4</td></tr>
<tr><td>data5</td></tr>
</table>
<table>
<tr>
<th>Name</th>
<th>College</th>
</tr>
<tr>
<td>testname1</td>
<td>college1</td>
</tr>
</table>
</body></html>
Firstly, I don't see any xsl:include declarations in any of these stylesheets, so I'm not quite sure what you are doing. [Sorry - missed the pale grey commented out code - poor contrast on my monitor.]
Secondly, with XSLT 1.0 the behaviour when you have two templates matching the same node, with the same precedence and priority, is not very well defined. Technically it's an error, but the processor is allowed to recover by choosing the rule that comes "last in the stylesheet" - which itself is not particularly well defined when there are multiple modules involved.
Thirdly, you say "the main xsl template is getting overridden instead of adding it to it". This suggests you have some particular expectation of how you want it to behave, but I can't really work out what this expectation is. You haven't given any expected results, so I don't know what you are trying to achieve. But it will always be the case, if you have more than one rule that matches a node, that you either get an error, or exactly one of the rules is executed - they are never combined in any way.
This could be achieved by modes.
Another way is to give each xsl:template match a priority number. The one which you want to get executed should have the highest priority. Priority is attribute of xsl:template
<xsl:template match = "employee" priority = "4"> do the task </xsl:template>
I need to loop over a group of values and print them into a two-column table.
I thought about following solution (must be xslt1)
<table class="main">
<xsl:for-each select="Attribute/Gruppe">
<xsl:if test="current()/#ID=20064490">
<xsl:variable name="open_row"><![CDATA[<tr><td style="width:50%;">
<xsl:value-of select="current()/#name" /></td>]]></xsl:variable>
<xsl:variable name="closing_row"><![CDATA[<td style="width:50%;">
<xsl:value-of select="current()/#name" /></td></tr>]]></xsl:variable>
<xsl:variable name="table">
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="(position() mod 2) = 1">
<xsl:value-of select="$open_row"
disable-output-escaping="yes" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$closing_row"
disable-output-escaping="yes" />
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<xsl:value-of select="$table"
disable-output-escaping="yes" />
</xsl:if>
</xsl:for-each>
</table>
I modified the code now I am using position() to find out if an closing <tr> or an opening </tr> is required.
The whole problem might be summarized to that you can not write single tags in XSLT. And that disable-output-escaping is not working.
Resulting HTML should be https://jsfiddle.net/dwetctm6/
For all the Nodes in the group. The order of the nodes in the table does not matter.
Furthermore assume following XML:
<bgroup>
<NODE1>text</NODE1>
<NODE2>text</NODE2>
<NODE n-1>text</NODE n-1>
<NODE n>text</NODE n>
</bgroup>
Dividing nodes into a two-column table is pretty trivial - especially if the order (across-first or down-first) does not matter.
Consider the following stylesheet:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/bgroup">
<table border="1">
<xsl:for-each select="*[position() mod 2 = 1]">
<tr>
<td><xsl:value-of select="."/></td>
<td><xsl:value-of select="following-sibling::*[1]"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
Applied to the following well-formed inpout:
XML
<bgroup>
<NODE1>A</NODE1>
<NODE2>B</NODE2>
<NODE3>C</NODE3>
<NODE4>D</NODE4>
<NODE5>E</NODE5>
</bgroup>
the result will be:
<table border="1">
<tr>
<td>A</td>
<td>B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
<tr>
<td>E</td>
<td/>
</tr>
</table>
rendered as:
Well, a few remarks must be made first of all:
You must learn how XSLT works: It is a language for templating that, being based on XML, must be composed in an ordered way: Every node open must be closed within the same scope. michael.hor257k is right: You shall not open a node within an scope and close it in another different one.
Also, there must be said that your input XML does not seem to be properly structured: It should be a repetition of nodes with same names and types. If all the NODE-n nodes are functionally or semantically equal, they should have the same name, no problem: You can have several nodes with the same name.
And now, the solution: Asuming your XML is as you have posted it, and since there can't be a templating definition based upon named nodes with different names, I have matched all the child nodes of the bgroup root node. So, the XSL can be as easy as this:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/bgroup">
<html>
<body>
<table>
<xsl:apply-templates select="*[position() mod 2 =1]"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="*">
<tr>
<td><xsl:value-of select="."/></td>
<td><xsl:value-of select="following-sibling::*[1]"/></td>
</tr>
</xsl:template>
</xsl:stylesheet>
It's important that you realise how, thanks to the ordered structure of the XSL language, you can see how the output will be with just a glimpse of the XSL template.
Sorry if my Post won´t be so good i am not that good in expressing myself.
What i want:
I´ve got an XML and a XSL Data i want to convert to an XSLT for an HTML.
As transformating i use Altova XMLSpy and this webpage: http://www.freeformatter.com/xsl-transformer.html
What i´ve got:
My XML:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="Style.xsl"?>
<Configuration>
<Environment>
...
</Environment>
<Configurations>
...
<Config>
...
</Config>
</Configurations>
</Configuration>
My XSL:
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<html>
<body>
<table border="4">
<xsl:apply-templates select="Configuration"/>
</table>
</body>
</html>>
</xsl:template>
<xsl:template match="Environment">
<tr>Environment</tr>
<br/>
<td> <th>Text</th>
<xsl:value-of select="Environment"/>
</td>
<td> <th>Text2</th>
<xsl:value-of select="config"/>
</td>
...
...
</xsl:template>
</xsl:stylesheet>
This is just a example how i build it.
so far everything was fine, but then:
Problem:
If i start my XML in Firefox now everything works. If i start it in IE or Chrome i just get the XML Data but not the Table.
Trying to transform it in XSLT gives me this Error:
Unable to perform XSL transformation on your XML file. null
I hope you can help me. I am a bloody beginner in XML/XSl/XSLT but i hope my post will give you the Information you need.
Greetings
Max
You have made a very common beginner's mistake:
<xsl:template match="Environment">
<tr>Environment</tr>...
<xsl:value-of select="Environment"/>
In this template, the context node is an Environment element, and your xsl:value-of instruction is looking for a child of that element with the name Environment. But your Environment element (I assume) does not have any Environment children. What you should write (I assume) is
<xsl:value-of select="."/>
However, I don't think this is the whole problem. It doesn't account for all the symptoms described. You've actually made another beginner's mistake, which is trying to run your XSLT code in the browser before testing it elsewhere. The browser-based XSLT engines give lousy diagnostics (even when you use something like Firebug). Get your code working first in a desktop environment - preferably an XML IDE like oXygen. You'll then get a decent explanation of what is wrong.
Hi Here Is The Modified Version of Your Code.
XSL Template Match Must match the XML node you wish to apply templates.
<?xml version="1.0" encoding="iso-8859-1"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:stylesheet version="2.0">
<xsl:template match="Configuration">
<html>
<body>
<table border="4">
<xsl:apply-templates select="Environment"/>
</table>
<table border="4">
<xsl:apply-templates select="Configurations"/>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="Environment">
<tr>
<th>
<xsl:value-of select="name()"/>
</th>
</tr>
<tr>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:template>
<xsl:template match="Configurations">
<tr>
<th>
<xsl:value-of select="name()"/>
</th>
</tr>
<tr>
<td>
<xsl:apply-templates select="Config"/>
</td>
</tr>
</xsl:template>
<xsl:template match="Config">
<tr>
<th>
<xsl:value-of select="name()"/>
</th>
</tr>
<tr>
<td>
<xsl:value-of select="."/>
</td>
</tr>
</xsl:template>
</xsl:stylesheet>
Hi I have two xsl files and I have one xml how can I combine these xsl files together at transform type and combine them it and get one html
index.html
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp " "><!ENTITY bull "•">]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:include href="hello.xsl"/>
<xsl:template match="/">
<html>
<tr>
<td><xsl:value-of select="name" /></td>
</tr>
</html>
</xsl:template>
</xsl:stylesheet>
and then my send xsl is
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE xsl:stylesheet [<!ENTITY nbsp " "><!ENTITY bull "•">]>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<table>
<tr>
<td><xsl:value-of select="age" /></td>
</tr>
</table>
</xsl:template>
</xsl:stylesheet>
and my xml is
<xml>
<name>abc</name>
<age>15</age>
</xml>
What I want output is like
<html>
<tr><td>abc</td></tr>
<table>
<tr><td>15</td></tr>
</table>
</html>
Is that is do able thing to perform in xsl I search so many site but couldn't find answer, plz help
EDIT: You edited your question and are now asking something completely different.
As I said, you can combine templates and other element from separate stylesheets with xsl:include and xsl:import. See the relevant section of the specification here.
There are ways to combine separate stylesheets (e.g. via xsl:include and xsl:import), but in your case I do not think it is even necessary.
Your stylesheets only have one template each and they simply retrieve values from an input XML which is a trivial action. There is really no need to store those two templates in separate stylesheets.
Write one stylesheet that produces both the html element and the table.
Let me emphasize another thing: It is evident in your question that you do not really understand the workings of both XSLT and HTML. To give a few hints:
the output you request is malformed HTML. A tr element cannot be an immediate child of html. Content must be placed inside body, as opposed to header.
both of the templates you show match /. Obviously, it makes no sense to combine them if they match the same node.
Please take the time to study the basics of XSLT and HTML before asking a new question.
Stylesheet
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="html" indent="yes"/>
<xsl:template match="/xml">
<html>
<body>
<table border="solid">
<tr>
<xsl:for-each select="*">
<td>
<xsl:value-of select="name()"/>
</td>
</xsl:for-each>
</tr>
<tr>
<td>
<xsl:value-of select="*[1]"/>
</td>
<td>
<xsl:value-of select="*[2]"/>
</td>
</tr>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Output
<html>
<body>
<table border="solid">
<tr>
<td>name</td>
<td>age</td>
</tr>
<tr>
<td>abc</td>
<td>15</td>
</tr>
</table>
</body>
</html>
I want to change this xml content to HTML table
<SSI>
<data>
<expanded>Chemical Research</expanded><abbre>Chem. Res.</abbre>
<expanded>Materials Journal</expanded><abbre>Mater. J.</abbre>
<expanded>Chemical Biology</expanded><abbre>Chem. Biol.</abbre>
<expanded>Symposium Series</expanded><abbre>Symp. Ser.</abbre>
<expanded>Biochimica Polonica</expanded><abbre>Biochim. Pol.</abbre>
<expanded>Chemica Scandinavica</expanded><abbre>Chem. Scand.</abbre>
<\data>
<data>
<expanded>Botany</expanded><abbre>Bot.</abbre>
<expanded>Chemical Engineering</expanded><abbre>Chem. Eng.</abbre>
<expanded>Chemistry</expanded><abbre>Chem.</abbre>
<expanded>Earth Sciences</expanded><abbre>Earth Sci.</abbre>
<expanded>Microbiology</expanded><abbre>Microbiol.</abbre>
<\data>
<\SSI>
Tried with following XSL
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html>
<head><title>Abbreviate</title></head>
<body>
<table border="1">
<tr>
<th>Expanded</th>
<th>Abbre</th>
</tr>
<xsl:for-each select="SSI/data">
<tr>
<td><xsl:value-of select="expanded"/></td>
<td><xsl:value-of select="abbre"/></td>
</tr>
</xsl:for-each>
</table>
</body></html>
</xsl:template>
</xsl:stylesheet>
I got only the first entry of data tag in HTML Table format
Expanded Abbre
----------- --------------------
Chemical Research Chem. Res
Botany Bot.
how can get all the values in HTMl???
If you clean up your XSLT and use xsl:apply-templates rather than xsl:for-each, life will become simpler. There is almost never a reason to use xsl:for-each. Try this:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
<html>
<head><title>Abbreviate</title></head>
<body>
<table border="1">
<tr>
<th>Expanded</th>
<th>Abbre</th>
</tr>
<xsl:apply-templates select='SSI/data/expanded'/>
</table>
</body></html>
</xsl:template>
<xsl:template match="expanded">
<tr>
<td><xsl:apply-templates/></td>
<xsl:apply-templates select='following-sibling::abbre[1]'/>
</tr>
</xsl:template>
<xsl:template match="abbre">
<td><xsl:apply-templates/></td>
</xsl:template>
</xsl:stylesheet>
By using small templates that are applied, you simplify your stylesheet. Additionally, there is no real reason to use xsl:value-of here - the built-in templates will do the right thing. You will end up with simpler templates that are easier to understand.