I want to split this node at <foo>:
<p>
<span>This is before foo.</span>
<foo>inside foo</foo>
<span>This is after foo.</span>
</p>
The result I want is
<p>
<span>This is before foo.</span>
</p>
<foo>inside foo</foo>
<p>
<span>This is after foo.</span>
</p>
But I'm getting
<p>
<span>This is before foo.</span>
<p>
<span>This is before foo.</span>
</p>
<foo>inside foo</foo>
<p>
<span>This is after foo.</span>
</p>
<span>This is after foo.</span>
</p>
And here's the style sheet I'm trying with:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.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="p">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
<xsl:template match="p/foo">
<xsl:element name="p">
<xsl:apply-templates select="preceding-sibling::node()"/>
</xsl:element>
<foo>
<xsl:apply-templates/>
</foo>
<xsl:element name="p">
<xsl:apply-templates select="following-sibling::node()"/>
</xsl:element>
</xsl:template>
</xsl:transform>
How can I get rid of that extra output?
Edit: Gave a more realistic example. See http://xsltransform.net/pNP88xQ/2
-- edited in response to your edited question --
This is not an easy task to accomplish in XSLT 1.0 (it's much easier to do in XSLT 2.0 using xsl:for-each-group).
One possible approach is a method known as sibling recursion:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()" name="identity">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<!-- start sibling recursion -->
<xsl:apply-templates select="node()[1]"/>
</xsl:template>
<!-- first node in a group -->
<xsl:template match="p/node()[not(self::foo)]">
<p>
<xsl:call-template name="identity"/>
<!-- collect the following node in this group -->
<xsl:apply-templates select="following-sibling::node()[1][not(self::foo)]" mode="collect"/>
</p>
<!-- continue recursion with the following divider -->
<xsl:apply-templates select="following-sibling::foo[1]"/>
</xsl:template>
<!-- other nodes in a group -->
<xsl:template match="node()" mode="collect">
<xsl:call-template name="identity"/>
<!-- collect the following node in this group -->
<xsl:apply-templates select="following-sibling::node()[1][not(self::foo)]" mode="collect"/>
</xsl:template>
<xsl:template match="foo">
<xsl:call-template name="identity"/>
<!-- restart sibling recursion -->
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
</xsl:stylesheet>
I have an XML of the following process
<p>
<contribution>
<authors><author>
<surname>Zhengxing</surname> <given-name>Chen</given-name>
</author> </authors>
</contribution>
</p>
But I need below format. Major problem is in space between surname and given-name. But after converting the file, space is gone.
<p>
<span class="contribution">
<span class="authors"><span class="author">
<span class="surname">Zhengxing</span> <span class="given-name">Chen</span>
</span> </span>
</span>
</p>
Thanks for advance.
Try this:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="p">
<xsl:element name="p"><xsl:apply-templates/></xsl:element>
</xsl:template>
<xsl:template match="contribution|authors|author|surname|given-name">
<xsl:element name="span">
<xsl:attribute name="class"><xsl:value-of select="name()"/></xsl:attribute>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
I am trying to make xslt script which display result in tabular format but I am getting result column value added in next row. please check image below for expected output.
Input xml file:
<?xml version="1.0"?>
<Softwares>
<SubNodes>
<Software>
<Results>
<Info>
<Name>Visual Studio</Name>
<Key>Name</Key>
<Value>2010</Value>
</Info>
<Info>
<Name>Visual Studio</Name>
<Key>Driver ID</Key>
<Value>DI8745</Value>
</Info>
</Results>
</Software>
<Software>
<Results>
<Info>
<Name>Oracle</Name>
<Key>Name</Key>
<Value>Oracle8</Value>
</Info>
<Info>
<Name>Oracle</Name>
<Key>Driver ID</Key>
<Value>ID2345</Value>
</Info>
</Results>
</Software>
<Software>
<Results>
<Info>
<Name>SQL</Name>
<Key>Name</Key>
<Value>SQL2005</Value>
</Info>
<Info>
<Name>SQL</Name>
<Key>Driver ID</Key>
<Value>ID8888</Value>
</Info>
</Results>
</Software>
</SubNodes>
</Softwares>
XSLT file:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w3="http://www.w3.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<table>
<tr>
<td>Name</td>
<td>Driver ID</td>
</tr>
<xsl:for-each select="//SubNodes/Software/Results/Info">
<tr>
<td>
<xsl:choose>
<xsl:when test="Key = 'Name'">
<xsl:value-of select="Value" />
</xsl:when>
</xsl:choose>
</td>
<td>
<xsl:choose>
<xsl:when test="Key = 'Driver ID'">
<xsl:value-of select="Value" />
</xsl:when>
</xsl:choose>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Current Output:
Image shows current output which is not giving result in row by row.
Expected output
Image shows expected output which is giving result in row by row.
Your XSLT will output a row for every Info. Try this instead:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w3="http://www.w3.org"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<table>
<tr>
<td>Name</td>
<td>Driver ID</td>
</tr>
<xsl:for-each select="//SubNodes/Software/Results">
<tr>
<td>
<xsl:choose>
<xsl:when test="Info[1]/Key = 'Name'">
<xsl:value-of select="Info[1]/Value" />
</xsl:when>
</xsl:choose>
</td>
<td>
<xsl:choose>
<xsl:when test="Info[2]/Key = 'Driver ID'">
<xsl:value-of select="Info[2]/Value" />
</xsl:when>
</xsl:choose>
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
I'm getting Attribute match is not allowed on this element errors on all these elements XAML except the root. I think I'm missing something about the syntax...
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="yes" indent="yes" />
<xsl:strip-space elements="*" />
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<body>
<xsl:apply-templates match="/Table"/>
<xsl:apply-templates match="/Paragraph"/>
</body>
</html>
</xsl:template>
<xsl:template match="Table">
<table>
<xsl:apply-templates match="TableRowGroup"/>
</table>
</xsl:template>
<xsl:template match="TableRowGroup">
<xsl:apply-templates match="TableRow"/>
</xsl:template>
<xsl:template match="TableRow">
<tr>
<xsl:apply-templates match="TableCell"/>
</tr>
</xsl:template>
<xsl:template match="TableCell">
<td>
</td>
</xsl:template>
</xsl:stylesheet>
Use <xsl:apply-templates select="..."/> instead of <xsl:apply-templates match="..."/>.
I have the below part of my XML Document. here when i run my xslt on this XML document, the col class ... inside colgroup is getting called, colgroup is getting called but end tag of col class is not getting called. please let me know how do i close col class... the last code contains my html output of xml.
<table frame="all" width="100%">
<tgroup cols="2">
<colspec colnum="1" colname="col1" colwidth="18%"/>
<colspec colnum="2" colname="col2" colwidth="82%"/>
<thead>
<row>
<entry namest="col1" nameend="col2">
<para>A timeline of British Virgin Islands company law</para>
</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<para>1884</para>
</entry>
<entry>
<para>Companies Act passed into law.</para>
</entry>
</row>
<row>
<entry>
<para>1984</para>
</entry>
<entry>
<para>International Business Companies Act passed into law.</para>
</entry>
</row>
<row>
<entry>
<para>2004</para>
</entry>
<entry>
<para>BVI Business Companies Act passed into law, coming into force on 1 January 2005.</para>
</entry>
</row>
<row>
<entry>
<para>2005</para>
</entry>
<entry>
<para>All three corporate statutes exist in parallel and it is possible to incorporate companies under any of them.</para>
</entry>
</row>
<row>
<entry>
<para>2006</para>
</entry>
<entry>
<para>Incorporation provisions in the International Business Companies Act and the Companies Act are repealed on 31 December 2005; the Acts remain in force but new companies may only be incorporated under the BVI Business Companies Act.</para>
</entry>
</row>
<row>
<entry>
<para>2007</para>
</entry>
<entry>
<para>International Business Companies Act repealed on 31 December 2006. Transitional provisions come into effect for companies incorporated under that act.</para>
</entry>
</row>
<row>
<entry>
<para>2009</para>
</entry>
<entry>
<para>Companies Act repealed on 31 December 2008. Transitional provisions come into effect for companies incorporated under that Act.</para>
</entry>
</row>
</tbody>
</tgroup>
</table>
and below is my xslt.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ntw="Number2Word.uri"
exclude-result-prefixes="ntw">
<xsl:variable name="ThisDocument" select="document('')"/>
<xsl:template match="/">
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8"/>
<title>
<xsl:value-of select="chapter/title"/>
</title>
<link rel="stylesheet" href="er:#css" type="text/css"/>
</head>
<body>
<xsl:apply-templates/>
<hr/>
<section class="tr_footnotes">
<xsl:apply-templates select="//footnote"
mode="footnote"/>
</section>
</body>
</html>
</xsl:template>
<xsl:template match="chapter">
<section>
<div class="chapter">
<a name="BVI-CH-{#num}"/>
<xsl:variable name="cnum">
<xsl:choose>
<xsl:when test="starts-with(#num,'0')">
<xsl:value-of select="substring-after(#num,'0')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="#num"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<div class="chapter-title">
<span class="chapter-num">
<xsl:value-of select="concat('Chapter ',$cnum,' ')"/>
</span>
<xsl:apply-templates select="title"/>
</div>
<xsl:apply-templates select="child::node()[not(self::title)]"/>
</div>
</section>
</xsl:template>
<xsl:template match="chapter/para">
<div class="para align-right">
<span class="format-smallcaps">Para</span>.
</div>
</xsl:template>
<!-- Index templates -->
<xsl:template name="toc" match="chapter/toc">
<div class="toc">
<xsl:call-template name="toc-part"/>
</div>
</xsl:template>
<xsl:template name="toc-part" match="chapter/toc/toc-part">
<div class="toc-part">
<xsl:call-template name="toc-div"/>
</div>
</xsl:template>
<xsl:template name="toc-div" match="chapter/toc/toc-part/toc-div">
<table class="toc-div">
<tbody>
<xsl:for-each select="current()/toc-part/toc-div/*">
<xsl:call-template name="toc-item"/>
</xsl:for-each>
</tbody>
</table>
</xsl:template>
<xsl:template name="toc-item" match="chapter/toc/toc-part/toc-div/toc-item">
<xsl:variable name="tocpg">
<xsl:value-of select="concat('#P',current()/toc-pg/text())"/>
</xsl:variable>
<xsl:variable name="tocpgtag" select="translate($tocpg,'.', '-')"/>
<xsl:variable name="chapternumber">
<!-- Get num attribute of parent node -->
<xsl:value-of select="ancestor::chapter[1]/#num"/>
</xsl:variable>
<xsl:variable name="itemlevel">
<xsl:value-of select="$ThisDocument//ntw:nums[#num=$chapternumber]/#word"/>
</xsl:variable>
<xsl:variable name="tocitemlevel">
<xsl:value-of select="concat('toc-item-', $itemlevel,'-level')"/>
</xsl:variable>
<table class="{$tocitemlevel}">
<tbody>
<tr>
<td class="toc-item-num">
<xsl:value-of select="current()/#num"/>
</td>
<td class="toc-title">
<xsl:value-of select="current()/toc-title"/>
</td>
<td class="toc-pg">
<a href="{$tocpgtag}">
<xsl:value-of select="current()/toc-pg"/>
</a>
</td>
</tr>
</tbody>
</table>
</xsl:template>
<!-- Index Templates Complete -->
<!-- Paragraph templates -->
<xsl:template name="section" match="section">
<!-- Variables-->
<xsl:variable name="classname">
<!--Get name attribute of current node -->
<xsl:value-of select="concat('section-',#level)"/>
</xsl:variable>
<xsl:variable name="chapternumber">
<!-- Get num attribute of parent node -->
<xsl:value-of select="ancestor::chapter[1]/#num"/>
</xsl:variable>
<xsl:variable name="sectnum">
<xsl:number level="any" count="section" format="1"/>
</xsl:variable>
<!--Create a string variable by concat string method -->
<xsl:variable name="sectionname">
<xsl:value-of select="concat('CH-',$chapternumber,'-SEC-0', $sectnum)"/>
</xsl:variable>
<!-- Template Content -->
<div class="{$classname}">
<a name="{$sectionname}"> </a>
<div class="section-title">
<span class="section-num">
<xsl:value-of select="#num"/>
</span>
<xsl:apply-templates select="title"/>
</div>
<xsl:apply-templates select="child::node()[not(self::title)]"/>
</div>
</xsl:template>
<xsl:template name="para" match="section/para">
<div class="para">
<xsl:apply-templates select="phrase"/>
<span class="phrase">
<xsl:value-of select="current()/phrase"/>
</span>
<xsl:apply-templates select="child::node()[not(self::phrase)]"/>
</div>
</xsl:template>
<xsl:template name="phrase" match="phrase">
<xsl:variable name="phrase">
<xsl:value-of select="concat('P',text())"/>
</xsl:variable>
<xsl:variable name="newphrase" select="translate($phrase,'.','-')"/>
<a>
<xsl:attribute name="name"><xsl:value-of select="$newphrase"></xsl:value-of></xsl:attribute>
</a>
</xsl:template>
<!-- Table Templates -->
<xsl:template name="table" match="table">
<table style="frame-{current()/#frame} width-{translate(current()/#width,'%','')}">
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template match="tgroup">
<colgroup>
<xsl:apply-templates select=".//colspec"/>
</colgroup>
<xsl:apply-templates select="child::node()[not(self::colspec)]"/>
</xsl:template>
<xsl:template name="tbody" match="tgroup/tbody">
<tbody>
<xsl:for-each select="current()/row">
<xsl:call-template name="row"/>
</xsl:for-each>
</tbody>
</xsl:template>
<xsl:template name="thead" match="tgroup/thead">
<xsl:for-each select="current()/row"><thead>
<tr>
<xsl:for-each select="current()/entry">
<xsl:call-template name="headentry"/>
</xsl:for-each>
</tr>
</thead>
</xsl:for-each>
</xsl:template>
<xsl:template name="colspec" match="colspec">
<col class="colnum-{current()/#colnum} colname-{current()/#colname} colwidth-{translate(current()/#colwidth,'%','')}"></col>
</xsl:template>
<xsl:template name="row" match="tbody/row">
<tr>
<xsl:for-each select="current()/entry">
<xsl:call-template name="entry"/>
</xsl:for-each>
</tr>
</xsl:template>
<xsl:template name="entry" match="entry">
<xsl:variable name="count">
<xsl:value-of select="count(preceding-sibling::* | following-sibling::*)"/>
</xsl:variable>
<xsl:choose>
<xsl:when test="$count < 2">
<xsl:if test="position()=1">
<td>
<div class="para align-center">
<xsl:value-of select="para[position()=1]"/>
</div>
</td>
<td>
<div class="para">
<xsl:value-of select="following-sibling::node()"/>
</div>
</td>
</xsl:if>
</xsl:when>
<xsl:when test="$count > 1">
<td>
<div class="para">
<xsl:apply-templates/>
</div>
</td>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="headentry">
<th>
<xsl:if test="translate(current()/#namest,'col','') != translate(current()/#nameend,'col','')">
<xsl:variable name="colspan">
<xsl:value-of select="translate(current()/#nameend,'col','') - translate(current()/#namest,'col','') + 1"/>
</xsl:variable>
<xsl:attribute name="colspan"><xsl:value-of select="$colspan"></xsl:value-of></xsl:attribute>
</xsl:if>
<div class="para">
<xsl:value-of select="current()/para/text()"/>
</div>
</th>
</xsl:template>
<!-- Table Templates complete -->
<!--List templates -->
<xsl:template name="orderedlist" match="orderedlist">
<ol class="orderedlist">
<xsl:apply-templates/>
</ol>
</xsl:template>
<xsl:template name="orderitem" match="orderlist/item">
<li class="item">
<xsl:apply-templates/>
</li>
</xsl:template>
<xsl:template name="orderitempara" match="item/para">
<xsl:variable name="itemnumber">
<xsl:value-of select="parent::item[1]/#num"/>
</xsl:variable>
<li class="item">
<div class="para">
<span class="item-num">
<xsl:value-of select="parent::item[1]/#num"/>
</span>
<xsl:apply-templates/>
</div>
</li>
</xsl:template>
<!--List templates Complete -->
<!-- Paragraph templates Complete -->
<!-- Footnote Templates-->
<xsl:template match="footnote">
<sup>
<a>
<xsl:attribute name="name"><xsl:text>footnoteref</xsl:text><xsl:number level="any" count="footnote" format="1"/></xsl:attribute>
<xsl:attribute name="href"><xsl:text>#footnote</xsl:text><xsl:number level="any" count="footnote" format="1"/></xsl:attribute>
<xsl:attribute name="class"><xsl:text>tr_ftn</xsl:text><xsl:number level="any" count="footnote" format="1"/></xsl:attribute>
<xsl:number level="any" count="footnote" format="1"/>
</a>
</sup>
</xsl:template>
<xsl:template match="footnote" mode="footnote">
<sup>
<li style="list-style-type:none;indent:0">
<a>
<xsl:attribute name="name"><xsl:text>footnote</xsl:text><xsl:number level="any" count="footnote" format="1"/></xsl:attribute>
<xsl:attribute name="href"><xsl:text>#footnoteref</xsl:text><xsl:number level="any" count="footnote" format="1"/></xsl:attribute>
<xsl:attribute name="class"><xsl:text>tr_ftn</xsl:text><xsl:number level="any" count="footnote" format="1"/></xsl:attribute>
<xsl:number level="any" count="footnote" format="1"/>
</a>
<xsl:text> </xsl:text>
<xsl:apply-templates/>
</li>
</sup>
</xsl:template>
<xsl:template match="footnote/para/uri">
<xsl:variable name="url1">
<xsl:value-of select="translate(#href, '<','')" />
</xsl:variable>
<xsl:variable name="url2">
<xsl:value-of select="translate($url1, '>','')" />
</xsl:variable>
<a href="{$url2}">
<xsl:value-of select="." />
</a>
</xsl:template>
<!-- Footnote Templates Complete -->
<xsl:template match="content-style">
<xsl:choose>
<xsl:when test="#format='smallcaps'">
<xsl:value-of select="translate(normalize-space(.),'ABCDEFGHIJKLMNOPQRSTUVWXZ','abcdefghijklmnopqrstuvwxyz')"/>
</xsl:when>
<xsl:when test="#format='superscript'">
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Namespace ntw-->
<ntw:nums num="01" word="first"/>
<ntw:nums num="02" word="second"/>
<ntw:nums num="03" word="third"/>
<ntw:nums num="04" word="forth"/>
<ntw:nums num="05" word="fifth"/>
<ntw:nums num="06" word="sixth"/>
<ntw:nums num="07" word="seventh"/>
<ntw:nums num="08" word="eighth"/>
<ntw:nums num="09" word="nighth"/>
<ntw:nums num="10" word="tenth"/>
<!-- Namespace ntw ends -->
</xsl:stylesheet>
HTML output of xml.
table style="frame-all width-100">
<colgroup>
<col class="colnum-1 colname-col1 colwidth-18"> //here / is missing in the end
<col class="colnum-2 colname-col2 colwidth-82">//here / is missing in the end
</colgroup>
Thanks
Welcome to Stack Overflow!
Your stylesheet does not specify an output method, but your output is recognizably HTML. So your stylesheet is using the HTML output method, and not the XML output method. In the HTML output method, elements which are always empty (like col) use an SGML-style end-tag, so the output you show is correct.
If you want XML output, add an xsl:output element to the stylesheet (as the first child of xsl:stylesheet) and specify method="xml" on it, thus:
<xsl:output method="xml"/>
(Note that if you are looking to create XHTML output, you will want to put your output elements in the XHTML namespace.)
When I add an output element to the stylesheet, the colgroup element in the output takes the following form, which appears to be what you're looking for:
<colgroup>
<col class="colnum-1 colname-col1 colwidth-18"/>
<col class="colnum-2 colname-col2 colwidth-82"/>
</colgroup>