My XML Code
<DBE:Attribute name="Test1" type="Table">
<DBE:Table>
<DBE:TableHeader>
<DBE:TableColumn>t1</DBE:TableColumn>
<DBE:TableColumn>t2</DBE:TableColumn>
<DBE:TableColumn>t3</DBE:TableColumn>
<DBE:TableColumn>t4</DBE:TableColumn>
<DBE:TableColumn>t5</DBE:TableColumn>
<DBE:TableColumn>t6</DBE:TableColumn>
<DBE:TableColumn>t7</DBE:TableColumn>
<DBE:TableColumn>t8</DBE:TableColumn>
<DBE:TableColumn>t9</DBE:TableColumn>
<DBE:TableColumn>t10</DBE:TableColumn>
<DBE:TableColumn>t11</DBE:TableColumn>
<DBE:TableColumn>t12</DBE:TableColumn>
<DBE:TableColumn>t13</DBE:TableColumn>
</DBE:TableHeader>
<DBE:TableRow>
<DBE:TableData>0300 </DBE:TableData>
<DBE:TableData/>
<DBE:TableData>25</DBE:TableData>
<DBE:TableData>25</DBE:TableData>
<DBE:TableData>2009/09/03</DBE:TableData>
<DBE:TableData/>
<DBE:TableData>BAG</DBE:TableData>
<DBE:TableData>rrr</DBE:TableData>
<DBE:TableData>Yes</DBE:TableData>
<DBE:TableData>12</DBE:TableData>
<DBE:TableData>2009/03/09</DBE:TableData>
<DBE:TableData>GO</DBE:TableData>
<DBE:TableData/>
</DBE:TableRow>
</DBE:Table>
</DBE:Attribute>
I would like my output to be ->
t7 t5 t1 t13 --> Header
---------------------------------------------------------------
BAG 2009/09/03 0300 GO --> ROW1
.............................................................. --> ROW2
and so on
My XSL code --> (for only selected values to be displayed)
<xsl:for-each select="DBE:Attribute[#name='Test1']/DBE:Table/DBE:TableRow">
<tr bgcolor="white">
<xsl:for-each select="DBE:TableData">
<td>
<xsl:value-of select="node()|*">
</xsl:value-of>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
You could create a selector variable that holds the numeric position of columns you want. See the variable named "selector" below. Once you have that, a simple if in your TableData and TableColumn templates does the rest.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:DBE="foo.bar">
<xsl:variable name="selector">;1;5;7;12;</xsl:variable>
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="DBE:Attribute">
<html>
<body><xsl:apply-templates/></body>
</html>
</xsl:template>
<xsl:template match="DBE:Table">
<table border="1">
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template match="DBE:TableHeader">
<tr>
<xsl:apply-templates select="DBE:TableColumn"/>
</tr>
</xsl:template>
<xsl:template match="DBE:TableColumn">
<xsl:variable name="pos">
<xsl:text>;</xsl:text><xsl:value-of select="string(position())"/><xsl:text>;</xsl:text>
</xsl:variable>
<xsl:if test="contains($selector, $pos)">
<th>
<xsl:value-of select="."/>
</th>
</xsl:if>
</xsl:template>
<xsl:template match="DBE:TableRow">
<tr>
<xsl:apply-templates select="DBE:TableData"/>
</tr>
</xsl:template>
<xsl:template match="DBE:TableData">
<xsl:variable name="pos">
<xsl:text>;</xsl:text><xsl:value-of select="string(position())"/><xsl:text>;</xsl:text>
</xsl:variable>
<xsl:if test="contains($selector, $pos)">
<td>
<xsl:value-of select="."/>
</td>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
Related
I have the following XSLT. It works great for horizontal layouts. However when there are too many columns I need it to flip to a vertical layout. Ultimately being able to configure or specify the number of columns in a variable would be best. Can anyone kindly help?
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" indent="yes"/>
<xsl:template match="/*">
<table>
<thead>
<tr>
<xsl:apply-templates select="*[1]/*" mode="th"/>
</tr>
</thead>
<tbody>
<xsl:apply-templates select="*"/>
</tbody>
</table>
</xsl:template>
<xsl:template match="/*/*/*" mode="th">
<th>
<xsl:value-of select="name()"/>
</th>
</xsl:template>
<xsl:template match="/*/*">
<tr>
<xsl:apply-templates select="*"/>
</tr>
</xsl:template>
<xsl:template match="/*/*/*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>
</xsl:stylesheet>
I am not sure I have understood the question correctly but if you just want to output several tables, each having $cols-per-table columns, then I think the adaption of the presented code to
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="cols-per-table" select="10"/>
<xsl:output method="html" indent="yes" doctype-system="about:legacy-doctype"/>
<xsl:template match="/">
<xsl:apply-templates select="*/*[1]/*[position() mod $cols-per-table = 1]" mode="page"/>
</xsl:template>
<xsl:template match="*" mode="page">
<xsl:param name="page-no" select="position()"/>
<table border="1">
<thead>
<xsl:apply-templates select=". | following-sibling::*[position() < $cols-per-table]" mode="th"/>
</thead>
<tbody>
<xsl:apply-templates select="/*/*">
<xsl:with-param name="page-no" select="$page-no"/>
</xsl:apply-templates>
</tbody>
</table>
</xsl:template>
<xsl:template match="/*/*/*" mode="th">
<th>
<xsl:value-of select="name()"/>
</th>
</xsl:template>
<xsl:template match="/*/*">
<xsl:param name="page-no"/>
<xsl:variable name="first-col" select="1 + $cols-per-table * ($page-no - 1)"/>
<xsl:variable name="last-col" select="$first-col + $cols-per-table - 1"/>
<tr>
<xsl:apply-templates select="*[position() >= $first-col and position() <= $last-col]"/>
</tr>
</xsl:template>
<xsl:template match="/*/*/*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/jyRYYjr/1
I have used XSLT 1.0 as the original code used that version although with XSLT 2/3 and positional grouping using for-each-group and/or a key computing the "pag" a "column" element belongs to might be more efficient:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:param name="cols-per-table" as="xs:integer" select="10"/>
<xsl:output method="html" indent="yes" html-version="5"/>
<xsl:key name="page-no" match="/*/*/*">
<xsl:variable name="index" as="xs:integer">
<xsl:number/>
</xsl:variable>
<xsl:sequence select="($index - 1) idiv $cols-per-table + 1"/>
</xsl:key>
<xsl:template match="/">
<xsl:for-each-group select="*/*[1]/*" group-adjacent="(position() - 1) idiv $cols-per-table">
<xsl:apply-templates select="." mode="page">
<xsl:with-param name="page-no" select="position()" tunnel="yes"/>
</xsl:apply-templates>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="*" mode="page">
<xsl:param name="page-no" tunnel="yes"/>
<table border="1">
<thead>
<xsl:apply-templates select="current-group()" mode="th"/>
</thead>
<tbody>
<xsl:apply-templates select="/*/*"/>
</tbody>
</table>
</xsl:template>
<xsl:template match="/*/*/*" mode="th">
<th>
<xsl:value-of select="name()"/>
</th>
</xsl:template>
<xsl:template match="/*/*">
<xsl:param name="page-no" tunnel="yes"/>
<tr>
<xsl:apply-templates select="key('page-no', $page-no, .)"/>
</tr>
</xsl:template>
<xsl:template match="/*/*/*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/jyRYYjr/4
At https://xsltfiddle.liberty-development.net/jyRYYjr/5 I have implemented a pure XSLT 3 approach solely using for-each-group and storing the "pages" and "columns" in a map.
The goal is simple. I'm trying to build a table with attributes in columns.
My problem : Some siblings don't have the same attributes as the first one.
When I build the table head I retrieve the attributes name of the first node and then hope that attributes of the following siblings will be the same in the same order. That is not the case.
I get only columns id, key, value, myattr1 and the myattr2 attribute is placed in the myattr1 column.
For building the table, I want to get columns : id, key, value, myattr1, myattr2
How can I retrieve the whole list of existing attributes for the node I am working on and loop over it?
I am still working the same js and form (see link at the bottom). It now requires bootstrap (css and js).
I slightly changed the xml. Here it is :
<?xml version="1.0" encoding="UTF-8"?>
<Domain>
<Properties id="myid">
<Property id="DOM00000" key="mykey1" value="value1" myattr2="Mail"/>
<Property id="DOM00001" key="mykey2" value="value2" myattr1="EveryDay"/>
</Properties>
<Tokens>
<Token name="token1" comment="" ><![CDATA[mydata1---blah-blah-blah]]></Token>
<Token name="token2" comment="" ><![CDATA[mydata2---blah-blah-blah]]></Token>
</Tokens>
<Resources>
<Resource name="res1" type="W" current="0">
<Value><![CDATA[10]]></Value>
</Resource>
<Resource name="res2" type="W" current="0">
<Value><![CDATA[10]]></Value>
</Resource>
</Resources>
</Domain>
The current state of the xsl :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/*">
<xsl:element name="div">
<xsl:attribute name="class">container</xsl:attribute>
<ul class="nav nav-tabs">
<xsl:for-each select="./*">
<xsl:call-template name="tabs" />
</xsl:for-each>
</ul>
</xsl:element>
<xsl:element name="div">
<xsl:attribute name="class">tab-content</xsl:attribute>
<xsl:for-each select="./*">
<xsl:call-template name="tabcontent" />
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template name="tabs">
<xsl:variable name="active">
<xsl:choose>
<xsl:when test="preceding-sibling::*"></xsl:when>
<xsl:otherwise>active</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="li">
<xsl:attribute name="class">nav-item <xsl:value-of select="$active" /></xsl:attribute>
<xsl:element name="a">
<xsl:attribute name="href">#<xsl:value-of select="name(.)" /></xsl:attribute>
<xsl:attribute name="class">nav-link</xsl:attribute>
<xsl:attribute name="data-toggle">tab</xsl:attribute>
<xsl:value-of select="name(.)" />
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template name="tabcontent">
<xsl:variable name="activetab">
<xsl:choose>
<xsl:when test="preceding-sibling::*"></xsl:when>
<xsl:otherwise>active in</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="div">
<xsl:attribute name="id"><xsl:value-of select="name(.)" /></xsl:attribute>
<xsl:attribute name="class">container tab-pane fade <xsl:value-of select="$activetab" /></xsl:attribute>
<h3><xsl:value-of select="name(.)" /></h3>
<table class="table table-striped table-hover">
<thead>
<tr><xsl:for-each select="./*[1]/#*"><th><xsl:value-of select="name(.)" /></th></xsl:for-each></tr>
</thead>
<tbody>
<xsl:for-each select="./*"><tr>
<xsl:for-each select="./#*"><td><xsl:value-of select="." /></td></xsl:for-each></tr>
</tr></xsl:for-each>
</tbody>
</table>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
XSLT - How to manage CDATA as common content?
Edit :
Thanks to Tim-C answer
Here is the full xsl working for my use case :
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="attrs" match="/*/*/*/#*" use="concat(name(../..), '|', name())" />
<xsl:template match="/*">
<xsl:element name="div">
<xsl:attribute name="class">container</xsl:attribute>
<ul class="nav nav-tabs">
<xsl:for-each select="./*">
<xsl:call-template name="tabs" />
</xsl:for-each>
</ul>
</xsl:element>
<xsl:element name="div">
<xsl:attribute name="class">tab-content</xsl:attribute>
<xsl:for-each select="./*">
<xsl:call-template name="tabcontent" />
</xsl:for-each>
</xsl:element>
</xsl:template>
<xsl:template name="tabs">
<xsl:variable name="active">
<xsl:choose>
<xsl:when test="preceding-sibling::*"></xsl:when>
<xsl:otherwise>active</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="li">
<xsl:attribute name="class">nav-item <xsl:value-of select="$active" /></xsl:attribute>
<xsl:element name="a">
<xsl:attribute name="href">#<xsl:value-of select="name(.)" /></xsl:attribute>
<xsl:attribute name="class">nav-link</xsl:attribute>
<xsl:attribute name="data-toggle">tab</xsl:attribute>
<xsl:value-of select="name(.)" />
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template name="tabcontent">
<xsl:variable name="activetab">
<xsl:choose>
<xsl:when test="preceding-sibling::*"></xsl:when>
<xsl:otherwise>active in</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="attrs" select="*/#*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />
<xsl:element name="div">
<xsl:attribute name="id"><xsl:value-of select="name(.)" /></xsl:attribute>
<xsl:attribute name="class">container tab-pane fade <xsl:value-of select="$activetab" /></xsl:attribute>
<h3><xsl:value-of select="name(.)" /></h3>
<table class="table table-striped table-hover">
<thead>
<tr>
<xsl:for-each select="$attrs">
<th>
<xsl:value-of select="name()" />
</th>
</xsl:for-each>
</tr>
</thead>
<tbody>
<xsl:for-each select="*">
<tr>
<xsl:variable name="current" select="." />
<xsl:for-each select="$attrs">
<td>
<xsl:value-of select="$current/#*[name() = name(current())]" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</table>
</xsl:element>
</xsl:template>
<xsl:template name="toto"></xsl:template>
</xsl:stylesheet>
What you make use of here is a technique called Muenchian Grouping to get a list of distinct attributes, based on their name.
However, although the question just mentions about id, key, value, myattr1, myattr2, which are the Property attributes, it looks like you want to repeat it for the Token and Resource nodes too (i.e. you are trying to be generic). In this case, you define a key like so, which takes into account the main element name
<xsl:key name="attrs" match="/*/*/*/#*" use="concat(name(../..), '|', name())" />
Then, for a given element (such as Properties) you can get distinct attributes like so:
<xsl:variable name="attrs" select="*/#*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />
This can then be used to get the headers, and access the relevant attributes for each row.
Try this (abridged) XSLT:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<xsl:key name="attrs" match="/*/*/*/#*" use="concat(name(../..), '|', name())" />
<xsl:template match="/*">
<xsl:for-each select="*">
<xsl:call-template name="tabcontent" />
</xsl:for-each>
</xsl:template>
<xsl:template name="tabcontent">
<xsl:variable name="attrs" select="*/#*[generate-id() = generate-id(key('attrs', concat(name(../..), '|', name()))[1])]" />
<table class="table table-striped table-hover">
<thead>
<tr>
<xsl:for-each select="$attrs">
<th>
<xsl:value-of select="name()" />
</th>
</xsl:for-each>
</tr>
</thead>
<tbody>
<xsl:for-each select="*">
<tr>
<xsl:variable name="current" select="." />
<xsl:for-each select="$attrs">
<td>
<xsl:value-of select="$current/#*[name() = name(current())]" />
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</tbody>
</table>
</xsl:template>
</xsl:stylesheet>
See it in action at http://xsltfiddle.liberty-development.net/jyRYYi7
I've the below line in XML.
<tb class="3">
<tr>
<td>
<b>English words </b>
</td>
<td>
<b>Arabic </b>
</td>
<td al="r">
<b>Arabic</b>
</td>
</tr>
<tr>
<td>bear </td>
<td>ḍam</td>
<td al="r">new</td>
</tr>
</tb>
Here is my xslt.
<xsl:template name="table" match="tb">
<table class="frame-all">
<xsl:call-template name="cols"/>
<xsl:apply-templates/>
</table>
</xsl:template>
<xsl:template name="cols">
<xsl:variable name="numbr" select="number(./#class)"/>
<xsl:variable name="colcnt" select="format-number(100 div $numbr,'##.#')"/>
<colgroup>
<!-- I want the condition here-->
</colgroup>
</xsl:template>
This gives me output of 33.3. And I want to create 3 cols(the class attribute value). And for each col the name should be increment value. as below.
<col name="1" width="33.3"/>
<col name="2" width="33.3"/>
<col name="3" width="33.3"/>
please let me know, how can i get the above result.
Thanks
Here is my answer.
<xsl:template name="table" match="tb">
<table class="frame-all">
<xsl:call-template name="cols"/>
<!--<xsl:apply-templates/>-->
</table>
</xsl:template>
<xsl:template name="colgroup">
<xsl:param name="count" select="./#cls"/>
<xsl:param name="final" select="1"/>
<xsl:variable name="colcnt" select="format-number(100 div number(./#cls),'##.#')"/>
<col class="colnum-{$final} colname-col{$final} colwidth-{$colcnt}"></col>
<xsl:if test="$final < $count">
<xsl:call-template name="colgroup">
<xsl:with-param name="final" select="$final +1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template name="cols">
<xsl:variable name="numbr" select="number(./#cls)"/>
<xsl:variable name="colcnt" select="format-number(100 div $numbr,'##.#')"/>
<colgroup>
<xsl:call-template name="colgroup"/>
</colgroup>
<xsl:for-each select="tr">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template match="tr">
<tr>
<xsl:apply-templates/>
</tr>
</xsl:template>
<xsl:template match="td">
<td>
<xsl:attribute name="align">
<xsl:choose>
<xsl:when test="./#al='r'">
<xsl:text>right</xsl:text>
</xsl:when>
<xsl:when test="./#al='c'">
<xsl:text>center</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>left</xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
<xsl:apply-templates/>
</td>
</xsl:template>
If you are using XSLT 2.0, then one way to generate a specific number of elements, in your case col elements, is to use a variation of the xsl:for-each to do a specific number of iterations.
So, instead of doing <xsl:call-template name="colgroup"/> to call a recursive template, you could do this:
<colgroup>
<xsl:for-each select="1 to xs:integer($numbr)">
<col name="{.}" width="{$colcnt}"/>
</xsl:for-each>
</colgroup>
Note that you will need to define the xs namespace prefix in your stylesheet as follows
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0">
I have this XML snippet
<MediaTypes>
<DVD>true</DVD>
<HDDVD>false</HDDVD>
<BluRay>true</BluRay>
</MediaTypes>
And I want to create an output that looks like this
DVD / Blu-ray
or like this
DVD
or like this
DVD / HD-DVD / Blu-ray
depending on the true/false states
But I'm a total beginner in the XSLT game. :-/
Here's a snippet of the full XML
<?xml version="1.0" encoding="Windows-1252"?>
<Collection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<DVD>
<ProfileTimestamp>2012-06-07T05:20:51Z</ProfileTimestamp>
<ID>0044005507027.5</ID>
<MediaTypes>
<DVD>true</DVD>
<HDDVD>false</HDDVD>
<BluRay>false</BluRay>
</MediaTypes>
<UPC>0-044005-507027</UPC>
<CollectionNumber>448</CollectionNumber>
<CollectionType IsPartOfOwnedCollection="true">Owned</CollectionType>
<Title>The Big Lebowski</Title>
<DistTrait />
<OriginalTitle />
<CountryOfOrigin>United States</CountryOfOrigin>
...
</DVD>
<DVD>
...
</DVD>
</Collection>
I tried to follow the advices given below (regarding the loop), but it doesn't seem to work.
This is the XSL I have so far (complete):
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template name="MediaTypes" match="MediaTypes">
Test
<xsl:for-each select="*[.='true']">
<xsl:value-of select="name()"/>
<xsl:if test="position()!=last()">
<xsl:text>/</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
<xsl:template match="/">
<html>
<head>
<title>DVD Profiler Double Dips</title>
</head>
<body>
<div>
<h1>DVD Profiler Double Dips</h1>
</div>
<table border="1" cellpadding="3" cellspacing="0">
<tr>
<th>Title</th>
<th>Edition</th>
<th>Production Year</th>
<th>DVD /</th>
<th>Purchase Date</th>
<th>Collection Type</th>
<th>Original Title</th>
<th>Sort Title</th>
</tr>
<xsl:for-each select="/Collection/DVD">
<tr>
<td>
<xsl:value-of select="Title"/>
</td>
<td>
<xsl:if test="DistTrait != ''">
<xsl:value-of select="DistTrait"/>
</xsl:if>
<xsl:if test="DistTrait = ''">
</xsl:if>
</td>
<td>
<xsl:if test="ProductionYear != ''">
<xsl:value-of select="ProductionYear"/>
</xsl:if>
<xsl:if test="ProductionYear = ''">
</xsl:if>
</td>
<td>
<xsl:call-template name="MediaTypes" />
</td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
But where
<xsl:call-template name="MediaTypes" />
is standing, only "Test" comes out
Yay!
You guys are awesome. Yes
<xsl:apply-templates select="MediaTypes"/>
Was my weapon of choice.
My final template looks like this:
<xsl:template name="MediaTypes" match="MediaTypes">
<xsl:for-each select="*[.='true']">
<xsl:value-of select="name()"/>
<xsl:if test="position()!=last()">
<xsl:text> / </xsl:text>
</xsl:if>
</xsl:for-each>
<xsl:if test="CustomMediaType != ''">
<xsl:if test="*[.='true']">
<xsl:text> / </xsl:text>
</xsl:if>
<xsl:value-of select="CustomMediaType"/>
</xsl:if>
</xsl:template>
begins to understand how stuff works
Thanks for all your help!
The question is rather trivial - the real problem is that you only show a snippet of the XML document. XSLT is very much context-dependent.
Here is a template to match any <MediaTypes> element and output the required string; hopefully you'll know how to incorporate it into your own stylesheet:
<xsl:template match="MediaTypes">
<xsl:for-each select="*[.='true']">
<xsl:value-of select="name()"/>
<xsl:if test="position()!=last()">
<xsl:text>/</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
I'd advice you to change the xml a bit
Here is an example
<?xml version="1.0" ?>
<?xml-stylesheet type="text/xsl" ?>
<MediaTypes>
<Media name="DVD">true</Media>
<Media name="HDDVD">false</Media>
<Media name="BluRay">true</Media>
</MediaTypes>
This way you may write XPATH expressions like //MediaTypes/Media
However did #michael.hor257k write a nice solution, jacking this xml pattern into that would look like this
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="//MediaTypes">
<xsl:for-each select="*[.='true']">
<xsl:value-of select="#name"/>
<xsl:if test="position()!=last()">
<xsl:text>/</xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This will render DVD/BluRay
Test here http://xslttest.appspot.com/
I have input xml of the form
<content xml:lang="en" xmlns:w="http://www.w.com/sch/W">
<w:firstRowHeader>true</w:firstRowHeader>
<w:firstColumnHeader>true</w:firstColumnHeader>
<w:customTable>
<w:tableContent>
<w:row>
<w:cell>
<w:spanInfo backgroundColor="Yellow" columnWidth="5" isRowHeader="true"/>
<text>ghnmghmg</text>
</w:cell>
<w:cell>
<w:spanInfo backgroundColor="Yellow" isRowHeader="false"/>
<text>ghmhgmgm</text>
</w:cell>
</w:row>
<w:row>
<w:cell>
<w:spanInfo backgroundColor="Yellow" columnWidth="5" isRowHeader="false"/>
<text>vj</text>
</w:cell>
<w:cell>
<w:spanInfo columnWidth="5" isRowHeader="true"/>
<text>mm</text>
</w:cell>
</w:row>
</w:tableContent>
</w:customTable>
</content>
This needs to be transformed to a xml in which:
w:tableContent mapped to tablecontent and
then under tablecontent tag 'table','tbody' tags are created
w:row mapped to tr tag
w:cell mapped to td tag
and conditions are like
if only 1st w:cell element in w:row has an attribute isRowHeader as "true" then every 'td' element under its respective 'tr' tag should contain a 'strong' tag and ignore 2nd w:cell's isRowHeader
if w:firstRowHeader is 'true' then transformed table should have 1st row text in bold, i.e., every 'td' tag in 1st row of table should contain 'strong' tag
if w:firstColumnHeader is 'true' then transformed table should have 1st column text in bold, i.e., every tr tag's 1st 'td' tag of table should contain 'strong' tag
Transformed xml:
<content>
<tablecontent>
<table cellspacing="1" cellpadding="1" border="1" style="WIDTH: 100%" title="Title" xmlns="http://www.w3.org/1999/xhtml">
<tbody>
<tr>
<td style="BACKGROUND-COLOR: Yellow; WIDTH: 5%"><strong>ghnmghmg</strong></td>
<td style="BACKGROUND-COLOR: Yellow"><strong>ghmhgmgm</strong></td>
</tr>
<tr>
<td style="BACKGROUND-COLOR: Yellow; WIDTH: 5%">vj</td>
<td style="WIDTH: 5%">mm</td>
</tr>
</tbody>
</table>
</tablecontent>
</content>
This is the xslt template that i have tried but cant figure out how to implement these 'strong' tags in it...
XSLT:
<xsl:template match="w:tableContent">
<xsl:variable name="var3" select="../w:firstRowHeader"/>
<xsl:variable name="var4" select="../w:firstColumnHeader"/>
<tablecontent>
<table cellspacing="1" cellpadding="1" border="1" style="WIDTH: 100%" title="Title" xmlns="http://www.w3.org/1999/xhtml" >
<tbody>
<xsl:for-each select="child::*">
<xsl:choose>
<xsl:when test="name()='w:row'">
<tr>
<xsl:for-each select="child::*">
<xsl:choose>
<xsl:when test="name()='w:cell'">
<td>
<xsl:for-each select="child::*">
<xsl:choose>
<xsl:when test="name()='w:spanInfo'">
<xsl:variable name="var8" select="#backgroundColor" />
<xsl:variable name="var9" select="#columnWidth" />
<xsl:variable name="var10" select="#isRowHeader" />
<xsl:if test="$var8!='' or $var9!=''">
<xsl:attribute name="style">
<xsl:if test="$var8!='' and $var9!=''">
<xsl:value-of select="concat('BACKGROUND-COLOR: ',$var8,'; WIDTH: ',$var9,'%')" />
</xsl:if>
<xsl:if test="$var8!='' and not($var9)">
<xsl:value-of select="concat('BACKGROUND-COLOR: ',$var8)" />
</xsl:if>
<xsl:if test="not($var8) and $var9!=''">
<xsl:value-of select="concat('WIDTH: ',$var9,'%')" />
</xsl:if>
</xsl:when>
<xsl:when test="name()='text'">
<xsl:if test="../w:spanInfo/#isRowHeader='true'">
<strong><xsl:value-of select="." /></strong>
</xsl:if>
<xsl:if test="../w:spanInfo/#isRowHeader!='true' or not(../w:spanInfo/#isRowHeader) ">
<xsl:value-of select="." />
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</td>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</tr>
</xsl:when>
</xsl:choose>
</xsl:for-each>
</tbody>
</table>
</tablecontent>
</xsl:template>
But the above template adds 'strong' tags to the cells which has only w:spanInfo's 'isRowHeader' attribute as 'true'. But I require to get 'strong' tag to be added to 2nd cell content also irrespective of its w:spanInfo's 'isRowHeader' attribute's value, provided if 1st cell already has 'isRowHeader' attribute as 'true'.
This XSLT 1.0 style-sheet ...
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:w="http://www.w.com/sch/W">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<content>
<xsl:apply-templates select="*/*/w:tableContent"/>
</content>
</xsl:template>
<xsl:template match="w:tableContent">
<table cellspacing="1" cellpadding="1" border="1" style="WIDTH: 100%" title="Title" xmlns="http://www.w3.org/1999/xhtml">
<tbody>
<xsl:apply-templates select="w:row" />
</tbody>
</table>
</xsl:template>
<xsl:template match="w:row">
<tr>
<xsl:apply-templates select="w:cell" />
</tr>
</xsl:template>
<xsl:template match="w:cell">
<xsl:variable name="style">
<xsl:if test="w:spanInfo/#backgroundColor">
<xsl:value-of select="concat('BACKGROUND-COLOR: ',w:spanInfo/#backgroundColor)" />
</xsl:if>
<xsl:if test="w:spanInfo/#columnWidth">
<xsl:if test="w:spanInfo/#backgroundColor">
<xsl:value-of select="'; '" />
</xsl:if>
<xsl:value-of select="concat('WIDTH: ',w:spanInfo/#columnWidth,'%')" />
</xsl:if>
</xsl:variable>
<td>
<xsl:if test="$style">
<xsl:attribute name="style"><xsl:value-of select="$style" /></xsl:attribute>
</xsl:if>
<xsl:apply-templates select="text" />
</td>
</xsl:template>
<xsl:template match="w:cell/text[
not( ../../preceding-sibling::w:row) and (/*/w:firstRowHeader='true')
or
not( ../preceding-sibling::w:cell) and (/*/w:firstColumnHeader='true')
or
(../preceding-sibling::w:cell[last()]/w:spaninfo/#isRowHeader='true')
]">
<strong><xsl:call-template name="default-rendering-of-text" /></strong>
</xsl:template>
<xsl:template match="text" name="default-rendering-of-text">
<xsl:value-of select="." />
</xsl:template>
</xsl:stylesheet>
... should satisfy your rules. The 3 conditions that you have set for bold/strong rendering are made plainly evident by the predicate of the match condition for text elements (near the end of the style-sheet). By avoiding unnecessary xsl:for-each we can use a simpler, more modular and more readable template based solution.