I need to convert a HTML file to XML format using XSLT 2.0. The HTML file contains only <p> tag with classes h1, h2, h3, . . .
<body>
<p class='h1'>the fisr A</p>
<p class='txt'>one</p>
<p>tow</p>
<p class='h2'>the sec B</p>
<p class='txt'>theree</p>
<p class='h2'>the sec sec B</p>
<p class='txt'>the next text</p>
<p class='h3'>the fisr C</p>
<p class='txt'>four</p>
<p class='txt'>five</p>
<p class='h1'>the seccond A</p>
<p class='txt'>the seccond txt</p>
<p class='h2'>the second B</p>
<p class='txt'>six</p>
<p class='txt'>seven</p>
<p class='h1'>the third A</p>
<p class='txt'>eight</p>
<p class='txt'>nine</p>
</body>
I need the XML output as shown below
<book>
<sectionA>
<title>the fisr A</title>
<p class="txt">one</p>
<p>tow</p>
<sectionB>
<title>the sec B</title>
<p class="txt">theree</p>
</sectionB>
<sectionB>
<title>the sec sec B</title>
<p class="txt">the next text</p>
<sectionC>
<title>the fisr C</title>
<p class="txt">four</p>
<p class="txt">five</p>
</sectionC>
</sectionB>
</sectionA>
<sectionA>
<title>the seccond A</title>
<p class="txt">the seccond txt</p>
<sectionB>
<title>the second B</title>
<p class="txt">six</p>
<p class="txt">seven</p>
</sectionB>
</sectionA>
<sectionA>
<title>the third A</title>
<p class="txt">eight</p>
<p class="txt">nine</p>
</sectionA>
</book>
Can anyone help me to get the desired output?
You can try this:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="body">
<book>
<xsl:for-each-group select="p" group-starting-with="p[#class='h1']">
<sectionA>
<title>
<xsl:value-of select="node()"/>
</title>
<xsl:for-each-group select="current-group() except ." group-starting-with="p[#class='h2']">
<xsl:choose>
<xsl:when test="self::p[#class='h2']">
<sectionB>
<title>
<xsl:value-of select="node()"/>
</title>
<xsl:for-each-group select="current-group() except ." group-starting-with="p[#class='h3']">
<xsl:choose>
<xsl:when test="self::p[#class='h3']">
<sectionC>
<title>
<xsl:value-of select="node()"/>
</title>
<xsl:apply-templates select="current-group() except ."></xsl:apply-templates>
</sectionC>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"></xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</sectionB>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"></xsl:apply-templates>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</sectionA>
</xsl:for-each-group>
</book>
</xsl:template>
<xsl:template match="p">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:apply-templates select="node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet> <!-- added by edit -->
Related
I want to group elements with #class="warning" and with #class="warninglistbullet" into a single .
Input:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Title</title>
</head>
<body>
<section>
<h1 class="heading1">A section</h1>
<p class="bodytext">Some bodytext.</p>
<p class="parts">1234</p>
<p class="parts">23456</p>
<p class="parts">2341</p>
<p class="bodytext">Some bodytext.</p>
<p class="warning">Eletrical hazard</p>
<p class="warning">Do not:</p>
<ul class="warninglistbullet">
<li class="warninglistbullet">
<p class="warninglistbullet">Take a bath and</p>
</li>
<li class="warninglistbullet">
<p class="warninglistbullet">use power tools at the same time.</p>
</li>
</ul>
</section>
</body>
</html>
Desired output:
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
<title>Title</title>
</head>
<body>
<section>
<h1 class="heading1">A section</h1>
<p class="bodytext">Some bodytext.</p>
<div class="parts">
<p class="parts">1234</p>
<p class="parts">23456</p>
<p class="parts">2341</p>
</div>
<p class="bodytext">Some bodytext.</p>
<div class="warning">
<p class="warning">Eletrical hazard</p>
<p class="warning">Do not:</p>
<ul class="warninglistbullet">
<li class="warninglistbullet">
<p class="warninglistbullet">Take a bath and</p>
</li>
<li class="warninglistbullet">
<p class="warninglistbullet">use power tools at the same time.</p>
</li>
</ul>
</div>
</section>
</body>
</html>
Current, wrong template:
<xsl:template match="section">
<xsl:element name="{local-name()}">
<xsl:apply-templates select="#*"/>
<xsl:for-each-group select="*[#class!='']" group-adjacent="#class">
<xsl:choose>
<xsl:when test="current-grouping-key = 'parts'">
<div class="parts">
<xsl:apply-templates select="current-group()"/>
</div>
</xsl:when>
<xsl:when test="(current-grouping-key = 'warning') or (current-grouping-key = 'warninglistbullet')">
<div class="warning">
<xsl:apply-templates select="current-group()"/>
</div>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:element>
</xsl:template>
I am able to group together elements with the same class, but how to group elements with different classes?
--
Apparently, Stackoverflow will not let me post the question because there is too much code and too little explanation.
So I will ramble on just to please the script that is preventing me from posting.
I tried both the "boolean" pattern and the "#class" pattern in the for-each-group element. I was not able to get either to work:
I do not know how to write the boolean pattern to match "parts" and "warning" and "warninglistbullet".
If I try to group-by class and evaluate the current-grouping-key() as "warning" OR "warningbulletitem", then the two elements never end up being grouped together.
How about:
<xsl:template match="section">
<xsl:copy>
<xsl:for-each-group select="*[#class!='']" group-adjacent="replace(#class, 'warninglistbullet', 'warning')">
<xsl:choose>
<xsl:when test="current-grouping-key() = ('parts', 'warning')">
<div class="{current-grouping-key()}">
<xsl:apply-templates select="current-group()"/>
</div>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
I have this specific flat input HTML structure:
<!DOCTYPE html>
<html>
<head>
<title>Article <b>bold</b> title</title>
</head>
<body>
<article>
<h1 class="h-title"><span class="span-title">1 </span> Title 1 with some <sup>sup</sup> elements.</h1>
<p>Some <b>bold</b> text for 1.</p>
<p>Some more <b>bold</b> text for 1.</p>
<h1 class="h-title"><span class="span-title">2 </span> Title 2 with some <sup>sup</sup> elements.</h1>
<ul>
<li>The first list item.</li>
<li>The second list item with <i>italic</i> text.</li>
</ul>
<p>Some <b>bold</b> text for 2.</p>
<h2 class="h-title"><span class="span-title">2.1</span> Title 2.1 with some <sup>sup</sup> elements.</h2>
<p>Some <b>bold</b> text for 2.1.</p>
<h2 class="h-title"><span class="span-title">2.2</span> Title 2.2 with some <sup>sup</sup> elements.</h2>
<p>Some <b>bold</b> text for 2.2.</p>
<h3 class="h-title"><span class="span-title">2.2.1</span> Title 2.2.1 with some <sup>sup</sup> elements.</h3>
<p>Some <b>bold</b> text for 2.2.1.</p>
<h3 class="h-title"><span class="span-title">2.2.2</span> Title 2.2.2 with some <sup>sup</sup> elements.</h3>
<p>Some <b>bold</b> text for 2.2.2.</p>
<h2 class="h-title"><span class="span-title">2.3</span> Title 2.3 with some <sup>sup</sup> elements.</h2>
<p>Some <b>bold</b> text for 2.3.</p>
<h1 class="h-title"><span class="span-title">3</span> Title 3 with some <sup>sup</sup> elements.</h1>
<p>Some <b>bold</b> text for 3.</p>
</article>
</body>
</html>
I would need to create a nested output XML structure as below:
<?xml version="1.0" encoding="UTF-8"?>
<xml>
<front type="head">
<title>Article <b>bold</b> title</title>
</front>
<body>
<sec id="s1" sec-type="Title 1 with some sup elements.">
<label>1</label>
<title>Title 1 with some <sup>sup</sup> elements.</title>
<p>Some <b>bold</b> text for 1.</p>
<p>Some more <b>bold</b> text for 1.</p>
</sec>
<sec id="s2" sec-type="Title 2 with some sup elements.">
<label>2</label>
<title>Title 2 with some <sup>sup</sup> elements.</title>
<list list-type="bullet">
<list-item>The first list item.</list-item>
<list-item>The second list item with <i>italic</i> text.</list-item>
</list>
<p>Some <b>bold</b> text for 2.</p>
<sec id="s2.1" sec-type="Title 2.1 with some sup elements.">
<label>2.1</label>
<title>Title 2.1 with some <sup>sup</sup> elements.</title>
<p>Some <b>bold</b> text for 2.1.</p>
</sec>
<sec id="s2.2" sec-type="Title 2.2 with some sup elements.">
<label>2.2</label>
<title>Title 2.2 with some <sup>sup</sup> elements.</title>
<p>Some <b>bold</b> text for 2.2.</p>
<sec id="s2.2.1" sec-type="Title 2.2.1 with some sup elements.">
<label>2.2.1</label>
<title>Title 2.2.1 with some <sup>sup</sup> elements.</title>
<p>Some <b>bold</b> text for 2.2.1.</p>
</sec>
<sec id="s2.2.2" sec-type="Title 2.2.2 with some sup elements.">
<label>2.2.2</label>
<title>Title 2.2.2 with some <sup>sup</sup> elements.</title>
<p>Some <b>bold</b> text for 2.2.2.</p>
</sec>
</sec>
<sec id="s2.3" sec-type="Title 2.3 with some sup elements.">
<label>2.3</label>
<title>Title 2.3 with some <sup>sup</sup> elements.</title>
<p>Some <b>bold</b> text for 2.3.</p>
</sec>
</sec>
<sec id="s3" sec-type="Title 3 with some sup elements.">
<label>3</label>
<title>Title 3 with some <sup>sup</sup> elements.</title>
<p>Some <b>bold</b> text for 3.</p>
</sec>
</body>
</xml>
So far, I have produced this XSLT transformation below (h1-h6 section needs to be improved I believe):
<?xml version="1.0" encoding="UTF-8"?>
<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:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- all -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- html / xml -->
<xsl:template match="html">
<xml>
<xsl:apply-templates select="node()|#*"/>
</xml>
</xsl:template>
<!-- head / front -->
<xsl:template match="head">
<front type="head">
<xsl:apply-templates select="node()|#*"/>
</front>
</xsl:template>
<!-- article / -->
<xsl:template match="article">
<xsl:apply-templates select="node()|#*"/>
</xsl:template>
<!-- h1-h6 / sec -->
<xsl:template match="h1[#class='h-title']">
<xsl:variable name="secId" select="normalize-space(span)"/>
<xsl:variable name="secType" select="substring-after(.,' ')"/>
<sec>
<xsl:attribute name="id" select="normalize-space(concat('s', $secId))"/>
<xsl:attribute name="sec-type" select="$secType"/>
<label>
<xsl:value-of select="$secId"/>
</label>
<title>
<xsl:apply-templates select="node() except span" />
</title>
</sec>
</xsl:template>
<!-- ul / list -->
<xsl:template match="ul">
<list list-type="bullet">
<xsl:apply-templates select="node()|#*"/>
</list>
</xsl:template>
<!-- li / list-item -->
<xsl:template match="li">
<list-item>
<xsl:apply-templates select="node()|#*"/>
</list-item>
</xsl:template>
</xsl:stylesheet>
Short description:
I have this flat HTML structure which needs to be transformed to nested XML structure. The original HTML structure may use h1 to h6 headings and they should be transformed into nested output XML sections accordingly. Each heading (h1...h6) has its own class (h1-title...h6-title). The HTML is always "well-structured", meaning h1 can be followed only by h2 or h3, etc. The wrong format (i.e. h1->h3->h2) may never occur.
I have two issues:
I believe the transformation needs to be done with recursion, but I am unable to figure it out with XSLT. I managed to create the right XML output structure and re-tag everything accordingly, but I'm unable to set nested structure.
The second (small) issue is that I don't know how to strip leading/trailing spaces from XML output tag and at the same time use "node() except span"? Function normalize-space() in this case returns an error.
I will be eternally grateful (and I mean it!) to someone who can solve this recursive mystery above for me.
Three days ago I touched the XSLT code for the first time. Today I'm posting my first "achievement" which is based on Martin Honnen's golden function (html(h)->xml(sec)). I believe the code is ugly and I don't know if it's written by all standards as it should be, but the end result is correct so I'll post it as an answer to my question for now. If there are some anomalities/issues still present, I'll be glad to fix it, if someone can comment.
It looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fn="http://www.w3.org/2005/xpath-functions"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="fn xs mf"
version="2.0">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<!-- all -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- html / xml -->
<xsl:template match="html">
<xml>
<xsl:apply-templates select="node()|#*"/>
</xml>
</xsl:template>
<!-- head / front -->
<xsl:template match="head">
<front type="head">
<xsl:apply-templates select="node()|#*"/>
</front>
</xsl:template>
<!-- flat html (h1-h6) to nested xml (sec) transformation -->
<xsl:function name="mf:group" as="node()*">
<xsl:param name="nodes" as="node()*"/>
<xsl:param name="level" as="xs:integer"/>
<xsl:for-each-group select="$nodes" group-starting-with="*[starts-with(local-name(), concat('h', $level))]">
<xsl:choose>
<xsl:when test="self::*[starts-with(local-name(), concat('h', $level))]">
<sec>
<xsl:apply-templates select="."/>
<xsl:sequence select="mf:group(current-group() except ., $level+1)"/>
</sec>
</xsl:when>
<xsl:when test="$level lt 6">
<xsl:sequence select="mf:group(current-group(), $level+1)"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:function>
<!-- article / -->
<xsl:template match="article">
<xsl:sequence select="mf:group(node(), 1)"/>
</xsl:template>
<!-- h1-h6 / sec -->
<xsl:template match="(h1|h2|h3|h4|h5|h6)[#class='h-title']">
<xsl:variable name="secId" select="normalize-space(span)"/>
<xsl:variable name="secType" select="fn:substring-after(normalize-space(.), ' ')"/>
<xsl:attribute name="id" select="normalize-space(concat('s', $secId))"/>
<xsl:attribute name="sec-type" select="$secType"/>
<label>
<xsl:value-of select="$secId"/>
</label>
<title>
<xsl:apply-templates select="node() except span" />
</title>
</xsl:template>
<!-- ul / list -->
<xsl:template match="ul">
<list list-type="bullet">
<xsl:apply-templates select="node()|#*"/>
</list>
</xsl:template>
<!-- li / list-item -->
<xsl:template match="li">
<list-item>
<xsl:apply-templates select="node()|#*"/>
</list-item>
</xsl:template>
</xsl:transform>
I want to wrap the headers and paragraph inside the section tags. Section tag ends when the next header arises.
Input:
<body>
<h2>text text</h2>
<p> some text </p>
<p> some text </p>
<h2> text text </h2>
<p> some text </p>
<p> some text </p>
<p> some text </p>
</body>
Output:
<body>
<section>
<h2>text text</h2>
<p> some text </p>
<p> some text </p>
</section>
<section>
<h2> text text </h2>
<p> some text </p>
<p> some text </p>
<p> some text </p>
</section>
</body>
Like mentioned in the comments, this is a grouping question.
If you're using XSLT 2.0, you can use xsl:for-each-group/#group-starting-with...
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/body">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:for-each-group select="*" group-starting-with="h2">
<section>
<xsl:copy-of select="current-group()"/>
</section>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
If you're stuck with XSLT 1.0, you can use an xsl:key based on a generated id of the h2...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="sectElems" match="/body/*[not(self::h2)]"
use="generate-id(preceding-sibling::h2[1])"/>
<xsl:template match="/body">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:apply-templates select="h2"/>
</xsl:copy>
</xsl:template>
<xsl:template match="h2">
<xsl:variable name="id">
<xsl:value-of select="generate-id()"/>
</xsl:variable>
<section>
<xsl:copy-of select=".|key('sectElems',$id)"/>
</section>
</xsl:template>
</xsl:stylesheet>
Both of these stylesheets produce the same output.
I am doing XML to HTML conversion and I worked out the xslt and on this, single problem still remains that I could not solve.
<?xml version="1.0" encoding="UTF-8"?>
<o>
<abstract-short type="string"><p>Last month a high court judge ruled that, for the purposes of inheritance tax, all let property is classed the sameā¦</p></abstract-short>
<content type="string"><p>Last month a<em>high court</em> judgr maydeal with weekly (or r queries and requests then it is still classed an investment, not a business.</p><p>An appeal against this<em>decision</em> destourist industry and the role it plays in the wider South West economy.</p></content>
<created type="string">2013-02-21T23:59:00</created>
<creator class="object">
<text type="string">[creatorName]</text>
<uri type="string">[creator]</uri>
</creator>
<identifier type="string">https://www.gazettes.co.uk/content/6</identifier>
<issued type="string">2013-06-31T23:59:00</issued>
<position type="string">related pane first</position>
<relation class="array">
<e type="string">wills-and-probate</e>
</relation>
<rights type="string">[copyrightattributionURI]</rights>
<source class="object">
<text type="string">Western Morning News</text>
<uri type="string">http://www.thisisdevon.co.uk/story-18208063-detail/story.html#axzz2M0VVYB82</uri>
</source>
<subject type="string">news</subject>
<title type="string">Arguing the case for appeal over tax ruling</title>
<weight type="string">0</weight>
</o>
And my xslt code is
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml" exclude-result-prefixes="#all">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="o">
<xsl:text disable-output-escaping="yes"><!DOCTYPE html></xsl:text>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
prefix="dcterms: http://purl.org/dc/terms/ dc: http://purl.org/dc/elements/1.1/ gz: https://www.gazettes.co.uk/metadata">
<xsl:apply-templates select="title"/>
</html>
</xsl:template>
<xsl:template match="o/title">
<head>
<title property="dc:title">
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:apply-templates/>
</title>
<meta name="dcterms.format" content="application/xhtml+xml"/>
<xsl:apply-templates
select="./parent::o/child::subject, ./parent::o/child::identifier, ./parent::o/child::relation, ./parent::o/child::position, ./parent::o/child::weight"
/>
</head>
<xsl:apply-templates select="./parent::o/child::created[#type='string']"/>
</xsl:template>
<!-- # Matching Meta content -->
<xsl:template match="o/created[#type='string']">
<body>
<article>
<header>
<h1 class="title">
<xsl:value-of select="./parent::o/child::title[#type='string']"/>
</h1>
</header>
<dl>
<dt>Created date</dt>
<dd property="dcterms:created">
<xsl:attribute name="content">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:value-of select="substring-before(., 'T')"/>
</dd>
<xsl:apply-templates select="./parent::o/child::issued, ./parent::o/child::source"/>
</dl>
<xsl:apply-templates
select="./parent::o/child::abstract-short, ./parent::o/child::abstract-long, ./parent::o/child::content"
/>
</article>
</body>
</xsl:template>
<xsl:template match="o/subject">
<meta name="dcterms.subject">
<xsl:attribute name="content">
<xsl:apply-templates/>
</xsl:attribute>
</meta>
</xsl:template>
<xsl:template match="o/identifier">
<meta name="dcterms.identifier">
<xsl:attribute name="content">
<xsl:apply-templates/>
</xsl:attribute>
</meta>
</xsl:template>
<xsl:template match="o/relation/e">
<meta name="dcterms.relation">
<xsl:attribute name="content">
<xsl:apply-templates/>
</xsl:attribute>
<xsl:attribute name="scheme">
<xsl:value-of select="'isPartOf'"/>
</xsl:attribute>
</meta>
</xsl:template>
<xsl:template match="o/position">
<meta name="gz.position">
<xsl:attribute name="content">
<xsl:apply-templates/>
</xsl:attribute>
</meta>
</xsl:template>
<xsl:template match="o/weight">
<meta name="gz.weight">
<xsl:attribute name="content">
<xsl:apply-templates/>
</xsl:attribute>
</meta>
</xsl:template>
<xsl:template match="o/issued">
<dt>Publication date</dt>
<dd property="dcterms:issued">
<xsl:attribute name="content">
<xsl:value-of select="."/>
</xsl:attribute>
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:value-of select="substring-before(., 'T')"/>
</dd>
</xsl:template>
<xsl:template match="o/source">
<dt>Source</dt>
<dd property="dc:source">
<xsl:attribute name="content">
<xsl:value-of select="./uri[#type='string']"/>
</xsl:attribute>
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:value-of select="./text[#type='string']"/>
</dd>
</xsl:template>
<!-- # Matching abstract short and long content -->
<xsl:template match="o/abstract-long">
<section class="abstract-long" property="dcterms:abstract">
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:for-each select="./*">
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:for-each>
</section>
</xsl:template>
<xsl:template match="o/abstract-short">
<section class="abstract-short" property="dcterms:abstract">
<xsl:attribute name="about">
<xsl:value-of select="./parent::o/child::identifier"/>
</xsl:attribute>
<xsl:for-each select="./*">
<xsl:element name="{name()}">
<xsl:apply-templates/>
</xsl:element>
</xsl:for-each>
</section>
</xsl:template>
<!-- # Matching body content -->
<xsl:template match="o/content">
<section class="content">
<xsl:for-each select="./*">
<xsl:element name="{name()}">
<xsl:for-each select="#*">
<xsl:attribute name="{local-name()}">
<xsl:value-of select="."/>
</xsl:attribute>
</xsl:for-each>
<xsl:apply-templates/>
</xsl:element>
</xsl:for-each>
</section>
</xsl:template>
<xsl:template match="o/rights"></xsl:template>
<xsl:template match="o/creator"></xsl:template>
</xsl:stylesheet>
But, here, my problem is, I did not get any child elements such as em, a from the template <xsl:template match="o/content". What's mistake I have made on this. please explain.Thanks in advance.
If you just want to copy all the children of <content>...</content> change your <xsl:template match="o/content"> to:
<xsl:template match="o/content">
<section class="content">
<xsl:copy-of select="node()"/>
</section>
</xsl:template>
I am an amateur and have started XML and XSLT recently.
I've been asked to make a XSLT file from the below XML.
<?xml version="1.0" encoding="UTF-8" ?>
<event>
<title>Test 1</title>
<description>The first test</description>
<location>
<postalcode>A1A 1A1</postalcode>
<city>Vancouver</city>
<province>BC</province>
<streetaddress>Arina street east</streetaddress>
</location>
<attendees>
<name>John</name>
<email>example#gmail.com</email>
<phone>778777777</phone>
</attendees>
</event>
I made this XSLT file
<?xml version="1.0" encoding="utf-8"?>
<!-- event.xsl -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<head><title><xsl:value-of select="title"/></title></head>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="event">
<h2><xsl:value-of select="title"/></h2>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="description">
<p><xsl:value-of select="description"/></p>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="location">
<p>
<xsl:value-of select="streetaddress"/>
<xsl:value-of select="city"/>
<xsl:value-of select="province"/>
<xsl:value-of select="postalcode"/>
</p>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="attendees">
<xsl:for-each select="event/attendees">
<p>
<xsl:value-of select="name"/>
<xsl:value-of select="email"/>
<xsl:value-of select="phone"/>
</p>
</xsl:for-each>
<xsl:apply-templates />
</xsl:template>
</xsl:stylesheet>
this is the generated HTML
<html>
<head>
<META http-equiv="Content-Type" content="text/html; charset=UTF-16">
<title></title></head>
<body>
<h2>Test 1</h2>
Test 1
<p></p>The first test
<p>Arina street eastVancouverBCA1A 1A1</p>
A1A 1A1
Vancouver
BC
Arina street east
John
example#gmail.com
778777777
</body>
</html>
this the desired html that I am looking for
<html>
<head>
<title>Test 1</title>
<body>
<h2>Test 1</h2>
<p>The first test</p>
<p>
Ariana Street East<br>
Vancouver<br>
BC , A1A 1A1<br>
</p>
<!-- repeat-->
<p>
Name:john<br>
Email:example#gmail.com<br>
Phone:77877777
</p>
<p>
Name:john2<br>
Email:example2#gmail.com<br>
Phone:77877778
</p>
</body>
</html>
when I make a HTML file it is kind of messed up.
would you let me know where are my mistakes?
do you have any easy explained article?
thank you
You may try this slightly adapted version:
<?xml version="1.0" encoding="utf-8"?>
<!-- event.xsl -->
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<head>
<title>
<xsl:value-of select="event/title"/>
</title>
</head>
<body>
<xsl:apply-templates />
</body>
</html>
</xsl:template>
<xsl:template match="title" />
<xsl:template match="event">
<h2>
<xsl:value-of select="title"/>
</h2>
<xsl:apply-templates />
</xsl:template>
<xsl:template match="description">
<p>
<xsl:value-of select="description"/>
</p>
</xsl:template>
<xsl:template match="location">
<p>
<xsl:value-of select="streetaddress"/>
<br/>
<xsl:value-of select="city"/>
<br/>
<xsl:value-of select="province"/>
<br/>
<xsl:value-of select="postalcode"/>
<br/>
</p>
</xsl:template>
<xsl:template match="attendees">
<p>
Name: <xsl:value-of select="name"/><br/>
Email: <xsl:value-of select="email"/><br/>
Phone: <xsl:value-of select="phone"/><br/>
</p>
</xsl:template>
</xsl:stylesheet>
Which will generate the following output:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Test 1</title>
</head>
<body>
<h2>Test 1</h2>
<p></p>
<p>Arina street east<br>Vancouver<br>BC<br>A1A 1A1<br></p>
<p>
Name: John<br>
Email: example#gmail.com<br>
Phone: 778777777<br></p>
</body>
</html>
I think you have an error in "attendess" pattern match:
<xsl:template match="attendees">
<xsl:for-each select="event/attendees">
<p>...
The "for-each" instruction is redundant, attendees template is applied from de "apply-templates" instruction in the event template.
The first title section wont work, update it to:
<title><xsl:value-of select="event/title"/></title>
add field names at the begining and elements at the end of the lines on attendees and location
<xsl:template match="location">
<p>
address:<xsl:value-of select="streetaddress"/><br>
city:<xsl:value-of select="city"/><br>
province:<xsl:value-of select="province"/><br>
postalcode:<xsl:value-of select="postalcode"/> <br>
</p>
<xsl:apply-templates />
</xsl:template>