Transforming XML to XSL with values on another location - html

I'm trying to convert my XML into an XSL.
I succeeded in making the first part, but now I'm stuck on the second part. I'm trying to obtain a value from a key where it is defined somewhere else.
Maybe its easier to just show u :
Incoming XML file:
<?xml version="1.0" encoding="utf-16"?>
<AXFRoot>
<MAObject type="default" mdclass="PROGRAM">
<GUID dmname="">201406121715517010024191178005056B93D790000004460B00000D0F000989</GUID>
<Meta name="VRT_ESSENCE_DURATION" format="string" frate="">355280</Meta>
<Meta name="VRT_ESSENCE_AUDIO_CHANNELS" format="string" frate="">4</Meta>
<Meta name="VRT_CLIP_ID" format="string" frate="" />
<StratumEx name="VRT_CONTENT">
<Group orderidx="0" id="0" lastchanged="00010101000000">
<Segment id="0" contentid="999e584a-7192-45ff-8570-af6587e2938f" begin="0" end="8600" />
<Segment id="1" contentid="23502d29-a0b4-48c5-a8b2-596a195e2768" begin="8640" end="19760" />
<Segment id="2" contentid="b246ffb6-a56f-4e4e-8bd9-5da3b9cd7351" begin="19800" end="34840" />
<Segment id="3" contentid="1643dde7-3c5d-4675-a52e-77d00b70309b" begin="49000" end="49000" />
<Segment id="4" contentid="5ce3968f-5324-4172-90f3-bd6d22f696a7" begin="54800" end="58480" />
</Group>
</StratumEx>
<StratumEx name="VRT_ITEMS">
<Group orderidx="0" id="0" lastchanged="00010101000000">
<Segment id="0" contentid="328626e6-c794-494d-939a-39f7aa2e5a85" begin="11120" end="49200" />
<Segment id="1" contentid="1effe83f-7076-418f-b86f-cbd6ac6ba7ba" begin="81200" end="86600" />
</Group>
</StratumEx>
<StratumEx name="VRT_RESTRICTION" />
</MAObject>
<MAObject type="default" mdclass="S_VRT_CONTENT">
<GUID dmname="">999e584a-7192-45ff-8570-af6587e2938f</GUID>
<Meta name="VRT_CONTENT_TXT" format="string" frate="">Frag1</Meta>
</MAObject>
<MAObject type="default" mdclass="S_VRT_CONTENT">
<GUID dmname="">23502d29-a0b4-48c5-a8b2-596a195e2768</GUID>
<Meta name="VRT_CONTENT_TXT" format="string" frate="">Frag2</Meta>
</MAObject>
<MAObject type="default" mdclass="S_VRT_CONTENT">
<GUID dmname="">b246ffb6-a56f-4e4e-8bd9-5da3b9cd7351</GUID>
<Meta name="VRT_CONTENT_TXT" format="string" frate="">Frag3</Meta>
</MAObject>
<MAObject type="default" mdclass="S_VRT_CONTENT">
<GUID dmname="">1643dde7-3c5d-4675-a52e-77d00b70309b</GUID>
<Meta name="VRT_CONTENT_TXT" format="string" frate="">Frag4</Meta>
</MAObject>
<MAObject type="default" mdclass="S_VRT_CONTENT">
<GUID dmname="">5ce3968f-5324-4172-90f3-bd6d22f696a7</GUID>
<Meta name="VRT_CONTENT_TXT" format="string" frate="">Frag5</Meta>
</MAObject>
<MAObject type="default" mdclass="S_VRT_ITEMS">
<GUID dmname="">328626e6-c794-494d-939a-39f7aa2e5a85</GUID>
<Meta name="VRT_ITEMS_TXT" format="string" frate="">Frag6</Meta>
</MAObject>
<MAObject type="default" mdclass="S_VRT_ITEMS">
<GUID dmname="">1effe83f-7076-418f-b86f-cbd6ac6ba7ba</GUID>
<Meta name="VRT_ITEMS_TXT" format="string" frate="">Frag7</Meta>
</MAObject>
</AXFRoot>
Wanted result:
<MediaHAVEN_external_metadata version="1.0" name="VIAA">
<MDProperties>
<MEDIA_ID>201406121715517010024191178005056B93D790000004460B00000D0F000989</MEDIA_ID>
<VRT_ESSENCE_DURATION>355280</VRT_ESSENCE_DURATION>
<VRT_ESSENCE_AUDIO_CHANNELS>4</VRT_ESSENCE_AUDIO_CHANNELS>
<VRT_CLIP_ID></VRT_CLIP_ID>
</MDProperties>
<fragments>
<fragment>
<title>Frag1</title>
<original_start_z>0</original_start_z>
<original_end_z>8600</original_end_z>
</fragment>
<fragment>
<title>Frag2</title>
<original_start_z>8640</original_start_z>
<original_end_z>19760</original_end_z>
</fragment>
<fragment>
<title>Frag3</title>
<original_start_z>19800</original_start_z>
<original_end_z>34840</original_end_z>
</fragment>
<fragment>
<title>Frag4</title>
<original_start_z>49000</original_start_z>
<original_end_z>49000</original_end_z>
</fragment>
<fragment>
<title>Frag5</title>
<original_start_z>54800</original_start_z>
<original_end_z>58480</original_end_z>
</fragment>
<fragment>
<title>Frag6</title>
<original_start_z>11120</original_start_z>
<original_end_z>49200</original_end_z>
</fragment>
<fragment>
<title>Frag7</title>
<original_start_z>81200</original_start_z>
<original_end_z>86600</original_end_z>
</fragment>
</fragments>
</MediaHAVEN_external_metadata>
As you can see, those contentid's will do a lookup for the 'Frag' data. In my example: http://xsltransform.net/94hvTzt The 'Frag' data that you see right now, shouldn't belong there..
Could anyone point me in the correct direction?
Thanks!

Firstly, don't do this to create elements in XSLT...
<xsl:text disable-output-escaping="yes"><</xsl:text><xsl:value-of select="#name" /><xsl:text disable-output-escaping="yes">></xsl:text>
That way lies madness. If you want to create dynamically named elements, use the xsl:element command. You just need to do this....
<xsl:element name="{#name}">
<xsl:value-of select="."/>
</xsl:element>
But in answer to your question, to look up date from another location in your XML document, use an xsl:key
<xsl:key name="fragment" match="MAObject" use="GUID" />
To use this key, to look up the data, you would just do something like this (assuming you were positioned on a segment element)
<xsl:value-of select="key('fragment', #contentid)/Meta" />
Try this XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="fragment" match="MAObject" use="GUID" />
<xsl:template match="/">
<MediaHAVEN_external_metadata version="1.0" name="VIAA">
<MDProperties>
<MEDIA_ID><xsl:value-of select="AXFRoot/MAObject[StratumEx]/GUID" /></MEDIA_ID>
<xsl:for-each select="AXFRoot/MAObject[StratumEx]/Meta">
<xsl:element name="{#name}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:for-each>
</MDProperties>
<fragments>
<xsl:for-each select="AXFRoot/MAObject/StratumEx/Group/Segment">
<fragment>
<title><xsl:value-of select="key('fragment', #contentid)/Meta" /></title>
<original_start_z><xsl:value-of select="#begin" /></original_start_z>
<original_end_z><xsl:value-of select="#end" /></original_end_z>
</fragment>
</xsl:for-each>
</fragments>
</MediaHAVEN_external_metadata>
</xsl:template>
</xsl:stylesheet>
Or maybe this, to take a more template-based approach
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:key name="fragment" match="MAObject" use="GUID" />
<xsl:template match="/">
<MediaHAVEN_external_metadata version="1.0" name="VIAA">
<xsl:apply-templates select="AXFRoot/MAObject[StratumEx]" />
</MediaHAVEN_external_metadata>
</xsl:template>
<xsl:template match="MAObject">
<MDProperties>
<MEDIA_ID><xsl:value-of select="GUID" /></MEDIA_ID>
<xsl:apply-templates select="Meta" />
</MDProperties>
<fragments>
<xsl:apply-templates select="StratumEx/Group/Segment" />
</fragments>
</xsl:template>
<xsl:template match="Meta">
<xsl:element name="{#name}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
<xsl:template match="Segment">
<fragment>
<title><xsl:value-of select="key('fragment', #contentid)/Meta" /></title>
<original_start_z><xsl:value-of select="#begin" /></original_start_z>
<original_end_z><xsl:value-of select="#end" /></original_end_z>
</fragment>
</xsl:template>
</xsl:stylesheet>

Related

Merging two XML files while transforming them using XSL

I have two XML files which I want to transform into one HTML file using XSL.
I transform them using xsltproc first.xml transform.xsl > output.html command in Linux terminal. Values from first.xml work perfectly and transform into HTML but I cannot force second.xml to work as well. It just didn't appear in file. I know there were questions like this on StackOverflow but I still couldn't figure out what I am doing wrong. It seems like something is wrong with match = "document('effects.xml')/effects" but I don't know what exactly.
first.xml
<elements>
<listOfElements>
<element>
*some data*
</element>
<element>
*some data*
</element>
</listOfElements>
</elements>
second.xml
<effects>
<effect>
<name> NAME1 </name>
<cost> COST1 </cost>
</effect>
<effect>
<name> NAME2 </name>
<cost> COST2 </cost>
</effect>
<effect>
<name> NAME3 </name>
<cost> COST3 </cost>
</effect>
</effect>
transform.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="/">
<xsl:text disable-output-escaping='yes'><!DOCTYPE html></xsl:text>
<html>
<head>
<meta charset="UTF-8"/>
<link rel="stylesheet" type="text/css" href="styl.css"/>
</head>
<body>
<xsl:apply-templates select="elements"/>
<xsl:apply-templates select="effects"/>
</body>
</html>
</xsl:template>
<xsl:template match="elements">
<div>
THIS WORKS
</div>
</xsl:template>
<xsl:template match="document('effects.xml')/effects">
<div>
<xsl:for-each select="effects/effect">
<div>
<p><xsl:value-of select="name"/></p>
</div>
</xsl:for-each>
</div>
</xsl:template>
Use <xsl:apply-templates select="document('effects.xml')/effects"/> and then in the match="effects" and <xsl:for-each select="effect">.

XML/XSLT nested loop of attributes to produce HTML table

I am trying to produce a HTML table from some XML I have got through a SQL query. The XML produced looks like the following:
<root>
<form attribute1="1" attribute2="1" />
<form attribute1="1" attribute2="2" />
<form attribute1="1" attribute2="3" />
<form attribute1="2" attribute2="1" />
<form attribute1="2" attribute2="2" />
<form attribute1="3" attribute2="1" />
</root>
The table I am trying to produce needs to have a header row for each unique attribute1 with rows underneath for each attribute2, something like this:
<attribute1="1" />
<attribute2="1" />
<attribute2="2" />
<attribute2="3" />
<attribute1="2" />
<attribute2="1" />
<attribute2="2" />
<attribute1="3" />
<attribute2="1" />
I don't have much experience using XML/XSLT but I am hoping it would be possible to do something like loop through the forms, create a header row for each unique attribute1 then create data rows associated to the unique attribute1 underneath.
If you can only use XSLT 1.0, try this XSLT for starters, which uses the Muenchian Grouping method
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:key name="form" match="form" use="#attribute1" />
<xsl:template match="root">
<xsl:copy>
<!-- Get first "form" element that occurs in each group -->
<xsl:for-each select="form[generate-id() = generate-id(key('form',#attribute1)[1])]">
<group>
<header><xsl:value-of select="#attribute1" /></header>
<!-- Get the "form" elements that make up the group -->
<xsl:apply-templates select="key('form', #attribute1)" />
</group>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="form">
<row><xsl:value-of select="#attribute2" /></row>
</xsl:template>
</xsl:stylesheet>
And here's some XSLT that can create an HTML table. This one is slightly more advanced as it works out the maximum number of columns for a row, and uses that in creating colspan attributes for the shorter rows
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:key name="form" match="form" use="#attribute1" />
<xsl:variable name="maxCells">
<xsl:for-each select="/root/form[generate-id() = generate-id(key('form',#attribute1)[1])]">
<xsl:sort select="count(key('form', #attribute1))" order="descending" />
<xsl:if test="position() = 1">
<xsl:value-of select="count(key('form', #attribute1))" />
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="root">
<table border="1">
<!-- Get first "form" element that occurs in each group -->
<xsl:for-each select="form[generate-id() = generate-id(key('form',#attribute1)[1])]">
<tr>
<th colspan="{$maxCells}">
<xsl:value-of select="#attribute1" />
</th>
</tr>
<tr>
<!-- Get the "form" elements that make up the group -->
<xsl:apply-templates select="key('form', #attribute1)" />
</tr>
</xsl:for-each>
</table>
</xsl:template>
<xsl:template match="form">
<td>
<xsl:if test="position() = last()">
<xsl:attribute name="colspan">
<xsl:value-of select="$maxCells - count(key('form', #attribute1)) + 1" />
</xsl:attribute>
</xsl:if>
<xsl:value-of select="#attribute2" />
</td>
</xsl:template>
</xsl:stylesheet>

XSLT for each loop not working

I have an xml file like this
<generic-cv:generic-cv xmlns:generic-cv="http://www.cihr-irsc.gc.ca/generic-cv/1.0.0" lang="en" dateTimeGenerated="2014-05-30 11:40:50">
<section id="f589cbc028c64fdaa783da01647e5e3c" label="Personal Information">
<section id="2687e70e5d45487c93a8a02626543f64" label="Identification" recordId="4f7c2ebd789f407b939e05664f6aa7c0">
<field id="ee8beaea41f049d8bcfadfbfa89ac09e" label="Title">
<lov id="00000000000000000000000000000318">Mr.</lov>
</field>
<field id="5c6f17e8a67241e19667815a9e95d9d0" label="Family Name">
<value type="String">ali</value>
</field>
<field id="98ad36fee26a4d6b8953ea764f4fed04" label="First Name">
<value type="String">Hara</value>
</field>
</section>
<section id="2687e70e5d45487c93a8a02626543f64" label="Identification" recordId="4f7c2ebd789f407b939e05664f6aa7c0">
<field id="ee8beaea41f049d8bcfadfbfa89ac09e" label="Title">
<lov id="00000000000000000000000000000318">Mr.</lov>
</field>
<field id="5c6f17e8a67241e19667815a9e95d9d0" label="Family Name">
<value type="String">fara</value>
</field>
<field id="98ad36fee26a4d6b8953ea764f4fed04" label="First Name">
<value type="String">hhh</value>
</field>
</section>
</section>
</generic-cv:generic-cv>
and an xslt file like this
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<head>
<title>Xml Convertor</title>
</head>
<body>
<h2><b> Personal Information</b></h2>
<xsl:for-each select=".//section[#id='2687e70e5d45487c93a8a02626543f64']" />
<ul>
<li>Name: <xsl:value-of select=".//field[#id='98ad36fee26a4d6b8953ea764f4fed04']/value" />, <xsl:value-of select=".//field[#id='5c6f17e8a67241e19667815a9e95d9d0']/value" /></li>
</ul>
</xsl:for-each>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I want loop through each section with a certain id number and print out the names in a list. Should look something like this
Hara
hhh
What i have tried so far is not working. Would someone be able to take a look and see what I did wrong
Here is the correct XSLT:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<head>
<title>Xml Convertor</title>
</head>
<body>
<h2><b> Personal Information</b></h2>
<ul>
<xsl:for-each select=".//section[#id='2687e70e5d45487c93a8a02626543f64']" >
<li>Name: <xsl:value-of select=".//field[#id='98ad36fee26a4d6b8953ea764f4fed04']/value" />, <xsl:value-of select=".//field[#id='5c6f17e8a67241e19667815a9e95d9d0']/value" /></li>
</xsl:for-each>
</ul>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I have check it with XSLT Tryit Editor from w3schools and this produces:
Personal Information
Name: Hara, ali
Name: hhh, fara
In your for-each loop you need to select the First Name and Family Name fields, instead of ids, as shown below:
<xsl:for-each select=".//section[#id='2687e70e5d45487c93a8a02626543f64']" >
<li><xsl:value-of select="field[#label='First Name']/value" />,<xsl:value-of select="field[#label='Family Name']/value" /></li>
</xsl:for-each>

How to convert all "LF" chars to "<br />" tag and show it on the HTML page

How to convert all LF chars to <br /> tags and show it on the HTML page?
I have the following example XML file:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="data.xslt"?>
<data>
<lines>
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
</lines>
</data>
and I want to show all lines on the HTML page. For this I use the following XSLT transformation:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="1.0" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
</head>
<body>
<xsl:variable name="filtered">
<xsl:call-template name="replace">
<xsl:with-param name="string" select="./data/lines"/>
<xsl:with-param name="search" select="'
'"/>
<xsl:with-param name="new"><br /></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<td align="left">
<xsl:value-of select="$filtered" disable-output-escaping="yes"/>
</td>
</body>
</html>
</xsl:template>
<xsl:template name="replace">
<xsl:param name="string"/>
<xsl:param name="search"/>
<xsl:param name="new"/>
<xsl:choose>
<xsl:when test="contains($string, $search)">
<xsl:value-of select="substring-before($string, $search)"/>
<xsl:value-of select="$new"/>
<xsl:call-template name="replace">
<xsl:with-param name="string" select="substring-after($string, $search)"/>
<xsl:with-param name="search" select="$search"/>
<xsl:with-param name="new" select="$new"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
When I open that XML file in Firefox (I use browser to show XSLT transformation) I will see that result:
Line 1Line 2Line 3Line 4Line 5Line 6
As you see, LF chars were not replaced by <br /> tags.
But when I use other string, for example EOL:
<xsl:with-param name="new">EOL</xsl:with-param>
I will see expected result:
EOLLine 1EOLLine 2EOLLine 3EOLLine 4EOLLine 5EOLLine 6EOL
The problem is with the convert/display <br /> tag.
You can pass a node fragment as a parameter value, as you do with <xsl:with-param name="new"><br /></xsl:with-param>, but to output that as a br element in your template you need to use <xsl:copy-of select="$new"/>, not xsl:value-of.
[edit] Here is an example: http://home.arcor.de/martin.honnen/xslt/test2012062801.xml. The stylesheet is at http://home.arcor.de/martin.honnen/xslt/test2012062801.xsl, I will also include it below:
<?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" version="4.01" encoding="utf-8" indent="yes"/>
<xsl:template match="/">
<html>
<head>
<title>Example</title>
</head>
<body>
<xsl:variable name="filtered">
<xsl:call-template name="replace">
<xsl:with-param name="string" select="data/lines"/>
<xsl:with-param name="search" select="'
'"/>
<xsl:with-param name="new"><br /></xsl:with-param>
</xsl:call-template>
</xsl:variable>
<div>
<xsl:copy-of select="$filtered"/>
</div>
</body>
</html>
</xsl:template>
<xsl:template name="replace">
<xsl:param name="string"/>
<xsl:param name="search"/>
<xsl:param name="new"/>
<xsl:choose>
<xsl:when test="contains($string, $search)">
<xsl:value-of select="substring-before($string, $search)"/>
<xsl:copy-of select="$new"/>
<xsl:call-template name="replace">
<xsl:with-param name="string" select="substring-after($string, $search)"/>
<xsl:with-param name="search" select="$search"/>
<xsl:with-param name="new" select="$new"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$string"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
You have extra quotes in your parameter value. Try changing the line...
<xsl:with-param name="search" select="'
'"/>
To...
<xsl:with-param name="search" select="
"/>
UPDATE
As pointed out by the OP, the above is incorrect and will cause an XSLT transformation error.
I believe the answer by #banana to be the correct one.
IMHO, xsl:anaylze-string is the perfect fit for this problem. This XSLT 2.0 style-sheet run under Saxon ...
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0"
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:so="http://stackoverflow.com/questions/11222334"
xmlns:x="http://www.w3.org/1999/xhtml"
xmlns="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="xsl fn xs so x">
<xsl:output method="xhtml" encoding="utf-8" indent="yes"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"
omit-xml-declaration="yes" />
<xsl:template match="/">
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head>
<body>
<xsl:apply-templates select="data/lines"/>
</body>
</html>
</xsl:template>
<xsl:template match="lines">
<xsl:analyze-string select="." regex="\n">
<xsl:matching-substring>
<br />
<xsl:value-of select="'
'" />
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:template>
</xsl:stylesheet>
... when applied to this input document ...
<?xml version="1.0" encoding="utf-8"?>
<data>
<lines>
Line 1
Line 2
Line 3
Line 4
Line 5
Line 6
</lines>
</data>
... will produce this html page ...
<!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" />
</head>
<body><br />
Line 1<br />
Line 2<br />
Line 3<br />
Line 4<br />
Line 5<br />
Line 6<br />
</body>
</html>
Try to replace:
<xsl:with-param name="new"><br /></xsl:with-param>
with:
<xsl:with-param name="new"><br /></xsl:with-param>
this will write current node value replacing \n with <br/>
<xsl:value-of select="replace(., '\n', '<br/>')"/>

XSLT formatting HTML Input

I am looking to use an XSLT to strip attributes out of an HTML file. The HTML file looks like this:
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>CB Comfy Bike</title>
<meta name="atg:string,index:$repositoryId" content="prod10005" />
<meta name="atg:date:creationDate" content="955050507" />
<meta name="atg:date:startDate" content="978325200" />
<meta name="atg:date:endDate" content="1009861200" />
<meta name="atg:string:$url"
content="atgrep:/ProductCatalog/frame-product/prod10005?locale=en_US" />
<meta name="atg:string,index:$baseUrl"
content="atgrep:/ProductCatalog/frame-product/prod10005" />
<meta name="atg:string:$repository.repositoryName" content="ProductCatalog" />
<meta name="atg:string:$itemDescriptor.itemDescriptorName" content="frame-product" />
<meta name="atg:string:childSKUs.$repositoryId" content="sku20007" />
<meta name="atg:string:childSKUs.$itemDescriptor.itemDescriptorName" content="bike-sku" />
<meta name="atg:date:childSKUs.creationDate" content="955068027" />
<meta name="atg:float:childSKUs.listPrice" content="400.0" />
<meta name="atg:float:childSKUs.salePrice" content="300.0" />
<meta name="atg:boolean:childSKUs.onSale" content="false" />
<meta name="atg:string:parentCategory.$repositoryId" content="cat55551" />
<meta name="atg:date:parentCategory.creationDate" content="956950321" />
<meta name="atg:string,docset:ancestorCategories.$repositoryId" content="cat10002" />
<meta name="atg:string,docset:ancestorCategories.$repositoryId" content="cat10003" />
<meta name="atg:string,docset:ancestorCategories.$repositoryId" content="cat55551" />
</head>
<body>
<div class="atg:role:displayName" id="0"> CB Comfy Bike </div>
<div class="atg:role:longDescription" id="1"> This bike is just right, whether you are a
commuter or want to explore the fire roads. The plush front suspension will smooth out
the roughest bumps and the big disc brakes provide extra stopping power for those big
downhills. </div>
<div class="atg:role:keywords" id="2"> mountain_bike comfort_bike </div>
<div class="atg:role:childSKUs.displayName" id="3"> CB Comfy Bike Medium </div>
<div class="atg:role:childSKUs.listPrice" id="4"> 400.0 </div>
<div class="atg:role:childSKUs.description" id="5"> Medium </div>
<div class="atg:role:parentCategory.displayName" id="6"> Mountain Bikes </div>
</body>
</html>
I am looking to at a new tag for each div, I have not focused on naming convensions yet, as it is proof of concept. However im not sure how to differenciate between div tags. This XSLT I have got so far is:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="head"/>
<xsl:template match="body">
<xsl:copy>
<xsl:value-of select="div/text()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Which returns:
<?xml version="1.0" encoding="utf-8"?>
<html>
<body> CB Comfy Bike </body>
</html>
How would i turn the input into something like this
<?xml version="1.0" encoding="UTF-8"?>
<root>
<tag1>CB Comfy Bike</tag1>
<tag2>This bike is just right, whether you are a
commuter or want to explore the fire roads. The plush front suspension will smooth out
the roughest bumps and the big disc brakes provide extra stopping power for those big
downhills.</tag2>
<tag3>mountain_bike comfort_bike</tag3>
<tag4>CB Comfy Bike Medium</tag4>
<tag5>400.0</tag5>
<tag6>Medium</tag6>
<tag7>Mountain Bikes</tag7>
</root>
The trouble i have is differentiating between the Div tags.
This short and simple transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<root>
<xsl:apply-templates select="body/div"/>
</root>
</xsl:template>
<xsl:template match="div">
<xsl:element name="tag{position()}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
when applied on the provided XML document:
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
<title>CB Comfy Bike</title>
<meta name="atg:string,index:$repositoryId" content="prod10005" />
<meta name="atg:date:creationDate" content="955050507" />
<meta name="atg:date:startDate" content="978325200" />
<meta name="atg:date:endDate" content="1009861200" />
<meta name="atg:string:$url"
content="atgrep:/ProductCatalog/frame-product/prod10005?locale=en_US" />
<meta name="atg:string,index:$baseUrl"
content="atgrep:/ProductCatalog/frame-product/prod10005" />
<meta name="atg:string:$repository.repositoryName" content="ProductCatalog" />
<meta name="atg:string:$itemDescriptor.itemDescriptorName" content="frame-product" />
<meta name="atg:string:childSKUs.$repositoryId" content="sku20007" />
<meta name="atg:string:childSKUs.$itemDescriptor.itemDescriptorName" content="bike-sku" />
<meta name="atg:date:childSKUs.creationDate" content="955068027" />
<meta name="atg:float:childSKUs.listPrice" content="400.0" />
<meta name="atg:float:childSKUs.salePrice" content="300.0" />
<meta name="atg:boolean:childSKUs.onSale" content="false" />
<meta name="atg:string:parentCategory.$repositoryId" content="cat55551" />
<meta name="atg:date:parentCategory.creationDate" content="956950321" />
<meta name="atg:string,docset:ancestorCategories.$repositoryId" content="cat10002" />
<meta name="atg:string,docset:ancestorCategories.$repositoryId" content="cat10003" />
<meta name="atg:string,docset:ancestorCategories.$repositoryId" content="cat55551" />
</head>
<body>
<div class="atg:role:displayName" id="0"> CB Comfy Bike </div>
<div class="atg:role:longDescription" id="1"> This bike is just right, whether you are a
commuter or want to explore the fire roads. The plush front suspension will smooth out
the roughest bumps and the big disc brakes provide extra stopping power for those big
downhills. </div>
<div class="atg:role:keywords" id="2"> mountain_bike comfort_bike </div>
<div class="atg:role:childSKUs.displayName" id="3"> CB Comfy Bike Medium </div>
<div class="atg:role:childSKUs.listPrice" id="4"> 400.0 </div>
<div class="atg:role:childSKUs.description" id="5"> Medium </div>
<div class="atg:role:parentCategory.displayName" id="6"> Mountain Bikes </div>
</body>
</html>
produces the wanted, correct result:
<root>
<tag1> CB Comfy Bike </tag1>
<tag2> This bike is just right, whether you are a
commuter or want to explore the fire roads. The plush front suspension will smooth out
the roughest bumps and the big disc brakes provide extra stopping power for those big
downhills. </tag2>
<tag3> mountain_bike comfort_bike </tag3>
<tag4> CB Comfy Bike Medium </tag4>
<tag5> 400.0 </tag5>
<tag6> Medium </tag6>
<tag7> Mountain Bikes </tag7>
</root>
Explanation:
Appropriate use of templates.
Use of the position() function.
Use of AVT (Attribute Value Templates).
Almost desired output )
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="head"/>
<xsl:template match="body">
<xsl:for-each select="div">
<xsl:element name="{concat('tag', position())}">
<xsl:value-of select="./text()"/>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
I'd do something similar to Timur but I wouldn't use the for-each. I'd use a template to iterate over the div's within the body
Applying the following to the supplied XML
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="html">
<xsl:apply-templates select="body"/>
</xsl:template>
<xsl:template match="body">
<root>
<xsl:apply-templates select="div"/>
</root>
</xsl:template>
<xsl:template match="div">
<xsl:element name="{concat('tag', position())}">
<xsl:value-of select="."/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
produces the desired output
<?xml version="1.0" encoding="UTF-8"?>
<root>
<tag1> CB Comfy Bike </tag1>
<tag2> This bike is just right, whether you are a
commuter or want to explore the fire roads. The plush front suspension will smooth out
the roughest bumps and the big disc brakes provide extra stopping power for those big
downhills. </tag2>
<tag3> mountain_bike comfort_bike </tag3>
<tag4> CB Comfy Bike Medium </tag4>
<tag5> 400.0 </tag5>
<tag6> Medium </tag6>
<tag7> Mountain Bikes </tag7>
</root>
Use of:
Identity transform
attribute value template
apply-templates to iterate over child nodes