I'm trying to convert from one XML (XHTML) file to another one with XSLT. I have to add some new elements and attributes, remove some elements and attributes as well as update the value of some existing attributes. So for with the valuable help given in this forum, I'm able to do many tasks as per the answer of my previous question: XML to XML with XSLT- Add, Remove, Modify Elements and Attributes but the problem arises when the elements have the same name and one same attribute. At that point I'm unable to distinguish it for modification.
For Example: I have two scripts of type="t/j" after the div tag where id="123" and one script of type="t/j" inside the head tag. I have to remove the script element where src="abc.js", only when it appears after the div tag (not inside the head tag) and change the value of xyz.js to lmn.js.
I have made comments in my source and desired file regarding the amendments. For eliminating the onClick event I'm passing a template match which does nothing using #onClick and it is removing the onClick event from everywhere as per the requirement.
However, when I apply the same technique for removing the 'span' tag from a specific location (commented in the source file) then it not only removes from there but from all the other places also where I don't want to. Please find my XML files below-
Source file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<script type="t/j" src="abc.js"></script>
</head>
<body>
<div id="o">
<div id="m">
<div id="nD">
<p id="nT">
Part 1</p>
</div>
<div class="TF" id="123">
<!--CHANGE THE VALUE OF XYZ.JS TO LMN.JS-->
<script type="t/j" src="xyz.js"></script>
<!--REMOVE THIS SCRIPT-->
<script type="t/j" src="abc.js"></script>
<div class="iD">
<img alt="" src="ic.gif" />
<span class="iDe">ABC</span><br/>
<div class="iDev">
<div id="ta12" class="bl" style="dis:bl"></div>
<div class="q">
<br/><br/>
<!--TO REMOVE SPAN TAG FROM HERE-->
<div id="ta12" class="bl" style="dis:bl">1<span style="color: #000000;"> XYZ</span> </div>
<!--REMOVE ONCLICK EVENT -->
<br/>T <input type="radio" name="op12" id="t12" onclick="getFeedback()"/>
F <input type="radio" name="op12" id="f12" onclick="getFeedback()"/>
<div>C </div>
<div>In </div>
<div>
<div></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body></html>
Desired file:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="t/j" src="abc.js"></script>
</head>
<script type="t/j" src="pqr.js"></script>
<script type="t/j" src="stu.js"></script>
<body onload="load()" onunload="unload()">
<div id="o">
<div id="m">
<div id="nD">
<p id="nT">
Part 1</p></div>
<div class="QT" id="456">
<script type="t/j" src="lmn.js"></script>
<form name="form1" id="q8" action="js:cal();">
<div class="iD">
<img alt="" src="ic.gif" />
<span class="iDe">ABC</span>
<div class="iDev">
<!--ADD THIS DIV TAG-->
<div class="pa" value="10"></div>
<div class="q">
<div id="ta8" class="bl" style="dis:bl">XYZ
</div><br/>
<input type="radio" name="ke8" value="0" />
<div id="tab8" class="bl" style="dis:bl">T
</div>
<input type="radio" name="ke8" value="1" />
<div id="tab8" class="bl" style="dis:bl">F
</div>
</div>
<br/><input type="submit" name="sub" value="Done"/>
</div></div>
</form>
</div>
</div>
</div>
</body></html>
I'm using XSLT 1.0. So for as per suggestions and some modifications (although it differs at some places like where id="1") my XSLT looks like:
UPDATED
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="xhtml">
<xsl:output method="xml" indent="yes" encoding="UTF-8"/>
<xsl:strip-space elements="*" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="xhtml:body">
<script type="t/j" src="pqr.js"></script>
<script type="t/j" src="stu.js"></script>
<body onload="loadPage()" onunload="unloadPage()">
<xsl:apply-templates select="#*|node()"/>
</body>
</xsl:template>
<xsl:template match="xhtml:div[#id='123']/#class">
<xsl:attribute name="class">QT</xsl:attribute>
<xsl:attribute name="id">456</xsl:attribute>
</xsl:template>
<xsl:template match="xhtml:script[#src='xyz.js']">
<xsl:copy>
<xsl:apply-templates select="#*[not(#src)]" />
<xsl:attribute name="src">lmn.js</xsl:attribute>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
<xsl:template match="xhtml:body//xhtml:script[#src='abc.js']" />
<xsl:template match="xhtml:div[#class='iD']">
<form name="form">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::xhtml:div[1]" mode="inside-form"/>
<br/><input type="submit" name="sub" value="Done"/>
</form>
</xsl:template>
<xsl:template match="xhtml:div[#id='ta12']">
<xsl:attribute name="class">pa</xsl:attribute>
<xsl:attribute name="value">10</xsl:attribute>
</xsl:template>
<xsl:template match="xhtml:div[#class='iDev']">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
<div id="ta8" class="bl" style="dis:bl">XYZ</div>
<br/>
<input type="radio" name="ke8" value="0" />
<div id="tab8" class="bl" style="dis:bl">T</div>
<input type="radio" name="ke8" value="1" />
<div id="tab8" class="bl" style="dis:bl">F</div>
</xsl:template>
</xsl:stylesheet>
THE OUTPUT WHICH I'M GETTING-
<?xml version="1.0" encoding="UTF-8"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<script type="t/j" src="abc.js" xml:space="preserve"/>
</head>
<script type="t/j" src="pqr.js"/>
<script type="t/j" src="stu.js"/>
<body onload="loadPage()" onunload="unloadPage()">
<div id="o">
<div id="m">
<div id="nD">
<p id="nT">
Part 1</p>
</div>
<!--VALUE OF CLASS HAS CHANGED BUT NOT ID-->
<div class="QT" id="123">
<script type="t/j" src="lmn.js" xml:space="preserve"/>
<form name="form">
<div class="iD">
<img alt="" src="ic.gif"/>
<span class="iDe">ABC</span>
<br clear="none"/>
<!--DIV TAG WITH CLASS=IDEV IS MISSING-->
<div class="pa" value="10">
<div class="q">
<!--BR HAVE APPEARED WITH ATTRIBUTE CLEAR-->
<br clear="none"/>
<br clear="none"/>
<!--INPUT TAGS HAVE APPEARED TWICE-->
<br clear="none"/>T <input type="radio" name="op12" id="t12" onclick="getFeedback()"/>
F <input type="radio" name="op12" id="f12" onclick="getFeedback()"/>
<div>C </div>
<div>In </div>
<div>
<div/>
</div>
</div>
</div>
<div id="ta8" class="bl" style="dis:bl">XYZ</div>
<br/>
<input type="radio" name="ke8" value="0"/>
<div id="tab8" class="bl" style="dis:bl">T</div>
<input type="radio" name="ke8" value="1"/>
<div id="tab8" class="bl" style="dis:bl">F</div>
</div>
<br/>
<input type="submit" name="sub" value="Done"/>
</form>
</div>
</div>
</div>
</body>
</html>
Thanking you!
In 90% of XSLT questions, the greatest challenge, is not the technical aspect of the question, but rather how to articulate the rules of transformation in the form of match pattern and corresponding output. Rather than give you a style-sheet, I'll give you a pattern & output view of your question. You should be able to make a style-sheet from this. There are no special techniques involved.
Comparing your input and output documents, I would describe the rules of transformation as follows.
Copy the input document to the output with the following exceptions.
Precede the <body> with the following literals
<script type="t/j" src="pqr.js" />
<script type="t/j" src="pqr.js" />
Append to the <body> element attributes #onload="load()" and #onunload="unload()".
For any <div> elements that have #id=123, change #class to QT and id to 456.
For any <script> elements change #src="xyz.js" to "lmn.js".
For any <script> elements in the body with #src="abc.js", delete.
Wrap any <div> elements that have #class="iD" in a <form> and just before the close of the form, include the following literals
<br/><input type="submit" name="sub" value="Done"/>
Replace any <div> elements with #id="ta12" with this replacement:
<div id="pa" value="10" />
Copy any <div class="iDev">, except replace its children with the following literals
<div id="ta8" class="bl" style="dis:bl">XYZ</div>
<br/>
<input type="radio" name="ke8" value="0" />
<div id="tab8" class="bl" style="dis:bl">T</div>
<input type="radio" name="ke8" value="1" />
<div id="tab8" class="bl" style="dis:bl">F</div>
Update
The OP has asked for a template for point 5. So here it is. This is a general solution on how to copy a node, just changing one attribute ...
<xsl:template match="xhtml:script[#src='xyz.js']">
<xsl:copy>
<xsl:apply-templates select="#*[not(#src)]" />
<xsl:attribute name="src">lmn.js</xsl:attribute>
<xsl:apply-templates select="node()" />
</xsl:copy>
</xsl:template>
If you didn't mind having a less general solution and could afford to assume that the script element would have no children and only one other attribute #type="t/j" , you could for example, use a more concise and specific template like so (but I would not recommend it - I am just laying out your options ...
<xsl:template match="xhtml:script[#src='xyz.js']">
<xhtml:script type="t/j" src="lmn.js" />
</xsl:template>
And for point 6 it is ...
<xsl:template match="xhtml:body//xhtml:script[#src='abc.js']" />
Related
I have a large number of html files with the following structure:
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>t</title>
</head>
<body>
<div class="z">
<div class="m">m1</div>
<div class="y">
<div class="a">a1</div>
<div class="b">b1</div>
<div class="x">
<div class="a">a2</div>
</div>
<div class="c">c1</div>
</div>
<div class="n">n1</div>
</div>
<div class="y">
<div class="c">c2</div>
<div class="d">d1</div>
<div class="x">
<div class="a">a3</div>
</div>
<div class="b">b2</div>
</div>
</body>
</html>
I want to:
Remove all div class="x" but keep its content; div class="x" have no text nodes
Rename all div class="y" to div class="x"; div class="y" have no text nodes
Order the nodes inside div class="x" in a specific order (not necessarily alphabetical): a, b, c, any other.
If there is more than one div class="a" there is no preference of their order; same for div class="b", div class="c", any other.
The final output should be like the following:
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>t</title>
</head>
<body>
<div class="z">
<div class="m">m1</div>
<div class="x">
<div class="a">a1
<div class="a">a2
<div class="b">b1
<div class="c">c1
</div>
<div class="n">n1</div>
</div>
<div class="x">
<div class="a">a3
<div class="b">b2
<div class="c">c2
<div class="d">d1
</div>
</body>
</html>
I utilise a shell script similar to the following:
xsltproc a.xslt a.html > b.html
where a.xslt is the following:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div[#class='x']" >
<xsl:apply-templates select="*|text()" />
</xsl:template>
<xsl:template match="div[#class='y']" >
<div class="x">
<xsl:apply-templates select="*|text()" />
</div>
</xsl:template>
</xsl:stylesheet>
My output is almost there, but the nodes are not in order: a, b, c, any other.
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>t</title>
</head>
<body>
<div class="z">
<div class="m">m1</div>
<div class="x">
<div class="a">a1</div>
<div class="b">b1</div>
<div class="a">a2</div>
<div class="c">c1</div>
</div>
<div class="n">n1</div>
</div>
<div class="x">
<div class="c">c2</div>
<div class="d">d1</div>
<div class="a">a3</div>
<div class="b">b2</div>
</div>
</body>
</html>
Do you have any suggestions on how to sort them in the correct order?
Are step 1 and 2 the correct approach to get this type of output, or should I use a different approach?
I am not sure if this will entirely suit your needs, but try this alternative template for matching div[#class='y']
<xsl:template match="div[#class='y']" >
<div class="x">
<xsl:apply-templates select="*[not(self::div[#class='x'])]|div[#class='x']/*">
<xsl:sort select="#class" />
</xsl:apply-templates>
</div>
</xsl:template>
This selects all child nodes of the div that are not #class="x", and also the direct child nodes of any divs that are #class="x"
You might be able to remove the template that matches div[#class='x'] in this case.
I am trying to replace certain div-tags with script-tags within any level.
The code within the div that is set to display none is what I need (discard the two outer divs), and the divs within that code that has a class of "is-script" must be replaced with script, while keeping its attributes and nodes.
Some examples of how the code can look:
<div data-type="embed">
<div style="display:none;">
<div class="is-script" src="http://example.js"></div>
</div>
</div>
<div data-type="embed">
<div style="display:none;">
<div class="is-script" src="http://example1.js"></div>
<div class="is-script" src="http://example2.js"></div>
</div>
</div>
<div data-type="embed">
<div style="display:none;">
<div>
<div class="is-script" src="http://example.js"></div>
</div>
</div>
</div>
<div data-type="embed">
<div style="display:none;">
<div>
<div class="is-script" src="http://example1.js"></div>
<div class="is-script" src="http://example2.js"></div>
</div>
</div>
</div>
<div data-type="embed">
<div style="display:none;">
<div>
<div class="is-script" src="http://example1.js"></div>
<div class="is-script">some inline javascript</div>
</div>
</div>
</div>
<div data-type="embed">
<div style="display:none;">
<iframe src="http://example.html" width="100%" height="400px"></iframe>
</div>
</div>
The actual json that the xsl is parsing:
<div data-type=\"embed\" style=\"width:545px;height:200px;background-color:#ccc;\">HTML EMBED
<div style=\"display:none;\">
<div class=\"is-script\">console.log(\"test1\");</div>
</div>
</div>
<div data-type=\"embed\" style=\"width:545px;height:200px;background-color:#ccc;\">HTML EMBED
<div style=\"display:none;\">
<div>
<div class=\"is-script\">console.log(\"test2\");</div>
</div>
</div>
</div>
<div data-type=\"embed\" style=\"width:545px;height:200px;background-color:#ccc;\">HTML EMBED
<div style=\"display:none;\">
<div class=\"is-script\" src=\"example.js\"></div>
</div>
</div>
<div data-type=\"embed\" style=\"width:545px;height:200px;background-color:#ccc;\">HTML EMBED
<div style=\"display:none;\">
<div>
<div class=\"is-script\" src=\"example.js\"></div>
</div>
</div>
</div>
<div data-type=\"embed\" style=\"width:545px;height:200px;background-color:#ccc;\">HTML EMBED
<div style=\"display:none;\">
<div>
<div class=\"is-script\" src=\"example1.js\"></div>
<div class=\"is-script\" src=\"example2.js\"></div>
<div class=\"is-script\" src=\"example3.js\"></div>
</div>
</div>
</div>
Wanted result:
<script class="is-script" src="http://example.js"></script>
<script class="is-script" src="http://example1.js"></script>
<script class="is-script" src="http://example2.js"></script>
<div>
<script class="is-script" src="http://example.js"></script>
</div>
<div>
<script class="is-script" src="http://example1.js"></script>
<script class="is-script" src="http://example2.js"></script>
</div>
<div>
<script class="is-script" src="http://example1.js"></script>
<script class="is-script">some inline javascript</script>
</div>
<iframe src="http://example.html" width="100%" height="400px"></iframe>
Current result:
<script class="was-script-tag">console.log("test1");</script>
<div>
<div class="was-script-tag">console.log("test2");</div>
</div>
<script class="was-script-tag" src="/templates/v1/js/sticky_article_v7.js?v0"></script>
<div>
<div class="was-script-tag" src="/templates/v1/js/sticky_article_v7.js?v1"></div>
</div>
<div>
<div class="was-script-tag" src="/templates/v1/js/sticky_article_v7.js?v2"></div>
<div class="was-script-tag" src="/templates/v1/js/sticky_article_v7.js?v2"></div>
<div class="was-script-tag" src="/templates/v1/js/sticky_article_v7.js?v2"></div>
</div>
My xsl:
<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" indent="yes"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div[#data-type='embed' or parent::div[#data-type='embed']]">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="div[#class='is-script']">
<script>
<xsl:apply-templates select="#*|node()"/>
</script>
</xsl:template>
</xsl:stylesheet>
So basically remove two outer divs, and keep everyting inside as is, except divs with class of "is-script" which must be renamed to script. The two outer divs will always be the same.
I have a basic understanding of xsl, but this is something I just can't make work.
Using xslt 2.
You could possibly start off with the identity template, which will copy all existing nodes without change
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
Then, to ignore the "outer two divs" you can add an overriding template like so:
<xsl:template match="div[#data-type='embed' or parent::div[#data-type='embed']]">
<xsl:apply-templates />
</xsl:template>
This ignores div elements with a data-type of embed, or its immediate child div.
Then to change the "is-script" divs to script elements you can add another template
<xsl:template match="div[#class='is-script']">
<script>
<xsl:apply-templates select="#*|node()"/>
</script>
</xsl:template>
Try this XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="div[#data-type='embed' or parent::div[#data-type='embed']]">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="div[#class='is-script']">
<script>
<xsl:apply-templates select="#*|node()"/>
</script>
</xsl:template>
</xsl:stylesheet>
I have this XML document:
<?xml version='1.0' encoding='UTF-8'?>
<content>
<text>
<img src='path/01.jpg'/>
<img src='path/02.jpg'/>
<img src='path/03.jpg'/>
</text>
</content>
I would like to transform it in the HTML struct that the jssor gallery requires. This is what I want:
<div class='gallery'>
<div data-u='loading' class='loading'>
<div></div>
<div></div>
</div>
<div data-u='slides' class='slides'>
<!-- each img tag will be transformed in to this. The rest of the html is just a fixed structure -->
<div>
<img data-u='image' src='path/01.jpg' />
<img data-u='thumb' src='path/01.jpg' />
</div>
<div>
<img data-u='image' src='path/02.jpg' />
<img data-u='thumb' src='path/02.jpg' />
</div>
<div>
<img data-u='image' src='path/03.jpg' />
<img data-u='thumb' src='path/03.jpg' />
</div>
</div>
<span data-u='arrowleft' class='arrowleft'></span>
<span data-u='arrowright' class='arrowright'></span>
<div data-u='thumbnavigator' class='thumbnavigator'>
<div data-u='slides' class='slides'>
<div data-u='prototype' class='p'>
<div class='w'>
<div data-u='thumbnailtemplate' class='t'></div>
</div>
<div class='c'></div>
</div>
</div>
</div>
</div>
This is what I'm doing in XSLT:
<xsl:transform version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:tpl='http://www.weblight.com.br/2015/XSL/Template'>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="content">
<div class='jssor_component galeria'>
<div data-u='loading' class='loading'>
<div><xsl:comment> </xsl:comment></div>
<div><xsl:comment> </xsl:comment></div>
</div>
<div data-u='slides' class='slides'>
<xsl:for-each select='text/img'>
<div>
<img data-u='image' src='{#src}'/>
<img data-u='thumb' src='{#src}'/>
</div>
</xsl:for-each>
</div>
<span data-u='arrowleft' class='arrowleft'><xsl:comment> </xsl:comment></span>
<span data-u='arrowright' class='arrowright'><xsl:comment> </xsl:comment></span>
<div data-u='thumbnavigator' class='thumbnavigator'>
<div data-u='slides' class='slides'>
<div data-u='prototype' class='p'>
<div class='w'>
<div data-u='thumbnailtemplate' class='t'></div>
</div>
<div class='c'><xsl:comment> </xsl:comment></div>
</div>
</div>
</div>
</div>
</xsl:template>
</xsl:transform>
But this is what I'm getting
<div class="jssor_component galeria">
<div data-u="loading" class="loading">
<div></div>
<div></div>
</div>
<div data-u="slides" class="slides"></div>
<span data-u="arrowleft" class="arrowleft"></span>
<span data-u="arrowright" class="arrowright"></span>
<div data-u="thumbnavigator" class="thumbnavigator">
<div data-u="slides" class="slides">
<div data-u="prototype" class="p">
<div class="w">
<div data-u="thumbnailtemplate" class="t" />
</div>
<div class="c"></div>
</div>
</div>
</div>
</div>
Seems to me like for-each not works like in thought, because the slide div is empty :/
After adding
<xsl:output method="xml" indent="yes"/>
as a child of the xsl:transform element in your XSLT so that the output XML will be readable, I do get the following output XML
<?xml version="1.0" encoding="UTF-8"?>
<div xmlns:tpl="http://www.weblight.com.br/2015/XSL/Template"
class="jssor_component galeria">
<div data-u="loading" class="loading">
<div><!----></div>
<div><!----></div>
</div>
<div data-u="slides" class="slides">
<div>
<img data-u="image" src="path/01.jpg"/>
<img data-u="thumb" src="path/01.jpg"/>
</div>
<div>
<img data-u="image" src="path/02.jpg"/>
<img data-u="thumb" src="path/02.jpg"/>
</div>
<div>
<img data-u="image" src="path/03.jpg"/>
<img data-u="thumb" src="path/03.jpg"/>
</div>
</div>
<span data-u="arrowleft" class="arrowleft"><!----></span>
<span data-u="arrowright" class="arrowright"><!----></span>
<div data-u="thumbnavigator" class="thumbnavigator">
<div data-u="slides" class="slides">
<div data-u="prototype" class="p">
<div class="w">
<div data-u="thumbnailtemplate" class="t"/>
</div>
<div class="c"><!----></div>
</div>
</div>
</div>
</div>
Which looks a lot like what you expected.
I see no way (analytically or empirically) that you could get XML output containing an empty data-u="slides" div as you indicated:
<div data-u="slides" class="slides"></div>
Surely
<xsl:for-each select='text/img'>
should be
<xsl:for-each select='div/img'>
I'm new to XSLT and I need to transform cross placed tags like:
<tabbable>
<tab name="tabname1"><content1></content1></tab>
<tab name="tabname2"><content2></content2></tab>
<tab name="tabname3"><content3></content3></tab>
</tabbable>
transform to:
<div>
<ul>
<li>tabname1</li>
<li>tabname2</li>
<li>tabname3</li>
</ul>
<div class="baltab">
<div><transformed-content1/></div>
<div><transformed-content2/></div>
<div><transformed-content3/></div>
</div>
</div>
Unfortunately I can't find detailed tutorials for XSLT.
The solution is simplest as i first think:
Only needs two for-each cycle, with right element selected:
input:
<?xml version="1.0" encoding="ISO-8859-1"?>
<tabbedpane>
<tab text="tablabel1">
<label text="tabcontent1"/>
</tab>
<tab text="tablabel2">
<label text="tabcontent2"/>
</tab>
<tab text="tablable3">
<label text="tabcontent3"/>
</tab>
the transform xml:
<xsl:template match="tabbedpane">
<div class="LFT tabbable">
<ul class="nav nav-tabs">
<xsl:for-each select="tab">
<li class="tab_label">
<xsl:value-of select="#text"/>
</li>
</xsl:for-each>
</ul>
<div class="tabs_holder">
<xsl:for-each select="tab">
<div class="single_tab">
<xsl:apply-templates/>
</div>
</xsl:for-each>
</div>
</div>
</xsl:template>
<xsl:template match="label">
<h6>
<xsl:if test="#id">
<xsl:attribute name="id">
<xsl:value-of select="#id" />
</xsl:attribute>
</xsl:if>
<xsl:value-of select="#text"/>
</h6>
</xsl:template>
and the result is:
<div class="LFT tabbable">
<ul class="nav nav-tabs">
<li class="tab_label">tablabel1</li>
<li class="tab_label">tablabel2</li>
<li class="tab_label">tablable3</li>
</ul>
<div class="tabs_holder">
<div class="single_tab">
<h6>tabcontent1</h6>
</div>
<div class="single_tab">
<h6>tabcontent2</h6>
</div>
<div class="single_tab">
<h6>tabcontent3</h6>
</div>
</div>
</div>
As i needed.
Experiencing some very odd behavior with, what should be, a very simple use of XSL and XSLT.
Here's a code sample.
<xsl:template match="check">
<div class="check">
<xsl:apply-templates mode="check">
<xsl:with-param name="checkName">testVariable</xsl:with-param>
</xsl:apple-templates>
</div>
</xsl:template>
The template called above
<xsl:template match="option" mode="check">
<xsl:param name="checkName" />
<div class="option">
<input type="checkbox">
</input>
<label>
testText
</label>
</div>
</xsl:template>
Pretty simple right?
It should, for each instance of a instance in the XML create a checkbox in a with a hard coded label.
However, what I'm getting is
<div class="check"></div>
<div class="option>Checkbox stuff here</div>
<div class="option>Checkbox stuff here</div>
<div class="option>Checkbox stuff here</div>
<div class="option>Checkbox stuff here</div>
<div class="check"></div>
<div class="option>Checkbox stuff here</div>
<div class="option>Checkbox stuff here</div>
<div class="option>Checkbox stuff here</div>
<div class="option>Checkbox stuff here</div>
Here's some sample XML
<check><option key="1"/><option key="0"/><option
key="0"/><option key="0"/><option
key="0"/></check>
Anyone know what's going on? :D
The problem is either in the XML-document/code you haven't shown to us or, less likely, you may be using a buggy XSLT processor.
This transformation (Your code wrapped within an <xsl:stylesheet>):
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="check">
<div class="check">
<xsl:apply-templates mode="check">
<xsl:with-param name="checkName">testVariable</xsl:with-param>
</xsl:apply-templates>
</div>
</xsl:template>
<xsl:template match="option" mode="check">
<xsl:param name="checkName" />
<div class="option">
<input type="checkbox"></input>
<label>testText</label>
</div>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<check>
<option key="1"/>
<option key="0"/>
<option key="0"/>
<option key="0"/>
<option key="0"/>
</check>
produces the wanted, correct result:
<div class="check">
<div class="option">
<input type="checkbox"></input>
<label>testText</label>
</div>
<div class="option">
<input type="checkbox"></input>
<label>testText</label>
</div>
<div class="option">
<input type="checkbox"></input>
<label>testText</label>
</div>
<div class="option">
<input type="checkbox"></input>
<label>testText</label>
</div>
<div class="option">
<input type="checkbox"></input>
<label>testText</label>
</div>
</div>
I have verified that the transformation produces identical results when run with:
Saxon 6.5.4
MSXML3, MSXML4, MSXML6
.NET XslCompiledTransform and XslTransform
Saxon 9.1.05
AltovaXML (XML-SPY)
XQSharp