If I select a DIV tag in a XHTML file with XSLT, like //*[#id='background'] How do I add a style, like a background color or other CSS styles like borders to the DIV? And if I have a list inside the DIV ID=background, how can I style the list, like removing the bullets? :)
This is really easy with XSLT. For instance, your input is:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title></title>
</head>
<body>
<div id="background">
<ul style="list-style-type: bullet">
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
</body>
</html>
You can use the identity transform to copy the input XML as is, and override the nodes of interest:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:x="http://www.w3.org/1999/xhtml"
exclude-result-prefixes="x">
<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="x:div[#id='background']">
<xsl:copy>
<xsl:attribute name="style">
<xsl:text>border-style:solid;border-width:medium</xsl:text>
</xsl:attribute>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="x:ul[ancestor::*
[name()='div' and #id='background']]/#style">
<xsl:attribute name="style">
<xsl:text>list-style-type: none</xsl:text>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
The output will be:
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title></title>
</head>
<body>
<div style="border-style:solid;border-width:medium" id="background">
<ul style="list-style-type: none">
<li>Coffee</li>
<li>Tea</li>
<li>Milk</li>
</ul>
</div>
</body>
</html>
Related
Here is my xslt:
<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.1" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes" doctype-system="about:legacy-compat" />
<xsl:template match="/">
<html>
<xsl:call-template name="header">
<xsl:with-param name="title">Strip Club List - Top 100
<xsl:choose>
<xsl:when test="/*/general/viewmethod='numcomments'">
Highest Number of Comments
</xsl:when>
<xsl:when test="/*/general/viewmethod='numreviews'">
Highest Number of Reviews
</xsl:when>
<xsl:when test="/*/general/viewmethod='highestreviews'">
Highest Rating
</xsl:when>
<xsl:when test="/*/general/viewmethod='numlikes'">
Highest Number of Likes
</xsl:when>
<xsl:when test="/*/general/viewmethod='numdislikes'">
Highest Number of Dislikes
</xsl:when>
<xsl:when test="/*/general/viewmethod='numfollowers'">
Highest Number of Followers
</xsl:when>
</xsl:choose>
<xsl:value-of select="/*/locations/name" /></xsl:with-param>
<xsl:with-param name="stylesheets">fonts.css,core.css,state.css,top.css</xsl:with-param>
<xsl:with-param name="scripts">core.js,state.js</xsl:with-param>
<xsl:choose>
<xsl:when test="/*/general/viewmethod='numcomments'">
<style>
.linked_location .rating {
right: 110px;
}
</style>
</xsl:when>
<xsl:when test="/*/general/viewmethod='numreviews'">
<style>
.linked_location .rating {
right: 100px;
}
</style>
</xsl:when>
</xsl:choose>
</xsl:call-template>
<body>
<div id="body"></div>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
Its being rendered in the head of the html document. The problem is that its not rendering onto the page. I believe it has to do with using style tags in an XSLT document.
XML:
<root>
<general>
<viewmethod>numreviews</viewmethod>
</general>
</root>
I also just tried:
<xsl:choose>
<xsl:when test="/*/general/viewmethod='numcomments'">
<style>
.linked_location .rating {
right: 110px;
}
</style>
</xsl:when>
<xsl:when test="/*/general/viewmethod='numreviews'">
<style>
.linked_location .rating {
right: 100px;
}
</style>
</xsl:when>
<xsl:when test="/*/general/viewmethod='highestreviews'">
<style>
.linked_location .rating {
right: 100px;
}
</style>
</xsl:when>
<xsl:when test="/*/general/viewmethod='numlikes'">
<style>
.linked_location .rating {
right: 90px;
}
</style>
</xsl:when>
<xsl:when test="/*/general/viewmethod='numdislikes'">
<style>
.linked_location .rating {
right: 90px;
}
</style>
</xsl:when>
<xsl:when test="/*/general/viewmethod='numfollowers'">
<style>
.linked_location .rating {
right: 90px;
}
</style>
</xsl:when>
</xsl:choose>
here is my header template
<xsl:template name="header">
<xsl:param name="title" />
<xsl:param name="keywords" />
<xsl:param name="description" />
<xsl:param name="stylesheets" />
<xsl:param name="scripts" />
<xsl:param name="emp" />
<head>
<xsl:if test="string-length($keywords) > 0"><meta name="keywords" content="{$keywords}" /></xsl:if>
<xsl:if test="string-length($description) > 0"><meta name="description" content="{$description}" /></xsl:if>
<xsl:if test="string-length($stylesheets) > 0"><xsl:call-template name="headercss"><xsl:with-param name="stylesheets" select="$stylesheets" /></xsl:call-template></xsl:if>
<xsl:if test="string-length($scripts) > 0"><xsl:call-template name="headerjs"><xsl:with-param name="scripts" select="$scripts" /></xsl:call-template></xsl:if>
<script src="http://domain/www/delivery/i.php?id=13&blockcampaign=1&target=_blank"></script>
<xsl:if test="$emp > 0">
<link rel="stylesheet" type="text/css" href="/emp/style.css" />
<script src="/emp/gl.js"></script>
<script src="/emp/tween.js"></script>
<script src="/emp/emp.js"></script>
</xsl:if>
<title><xsl:value-of select="$title" /></title>
</head>
</xsl:template>
thanks
As mentioned in comments xsl:choose can not be a child of xsl:call-template. See http://www.w3.org/TR/xslt#named-templates for the syntax. It is possible that the XSLT processor you are using is simply ignoring the xsl:choose in this case, rather than throwing an error.
What you probably need to do, is add a style parameter to your header template, and then pass in the style using xsl:with-param in a similar manner to the other parameters.
Try this XSLT as a slimmed down example:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="UTF-8" omit-xml-declaration="yes" doctype-system="about:legacy-compat" />
<xsl:template match="/">
<html>
<xsl:call-template name="header">
<xsl:with-param name="title">Test</xsl:with-param>
<xsl:with-param name="keywords" select="/root/general/viewmethod" />
<xsl:with-param name="style">
<xsl:choose>
<xsl:when test="/*/general/viewmethod='numcomments'">
<style>
.linked_location .rating {
right: 110px;
}
</style>
</xsl:when>
<xsl:when test="/*/general/viewmethod='numreviews'">
<style>
.linked_location .rating {
right: 100px;
}
</style>
</xsl:when>
</xsl:choose>
</xsl:with-param>
</xsl:call-template>
<body>
<div id="body"></div>
</body>
</html>
</xsl:template>
<xsl:template name="header">
<xsl:param name="title" />
<xsl:param name="keywords" />
<xsl:param name="style" />
<head>
<xsl:if test="string-length($keywords) > 0"><meta name="keywords" content="{$keywords}" /></xsl:if>
<xsl:copy-of select="$style" />
<title><xsl:value-of select="$title" /></title>
</head>
</xsl:template>
</xsl:stylesheet>
I am quite new to xslt, so any help will be much appreciated. Below is my sample xml file.
<DocumentElement>
<Records>
<date>2014-07-01 00:00</date>
</Records>
<Records>
<date>2014-08-03 00:00</date>
</Records>
<Records>
<date>2013-08-03 00:00</date>
</Records>
<DocumentElement>
What I need is just to select distinct years from the dates.
Currently I have the below xslt which brings duplicate years.
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:ms="urn:schemas-microsoft-com:xslt">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="years" select="DocumentElement/Records/date"/>
<ul>
<xsl:for-each select="$years">
<li>
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="concat('?archive=',substring( ., 1, 4))"/>
</xsl:attribute>
<xsl:value-of select="substring( ., 1, 4)"/>
</xsl:element>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
Which gives me the results below:
<ul>
<li>
2014
</li>
<li>
2014
</li>
<li>
2013
</li>
</ul>
But my expected result should be
<ul>
<li>
2014
</li>
<li>
2013
</li>
</ul>
I tried the following below but I get empty output
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" xmlns:ms="urn:schemas-microsoft-com:xslt">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:variable name="years" select="substring(DocumentElement/Records/date, 1, 4)"/>
<ul>
<xsl:for-each select="$years[not(.=preceding::*)]">
<li>
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="concat('?archive=',substring( ., 1, 4))"/>
</xsl:attribute>
<xsl:value-of select="substring( ., 1, 4)"/>
</xsl:element>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
Any help will be much appreciated. thanks.
Muenchian grouping is much more effective way of grouping in XSLT1.0 than using preceding/following/preceding-sibling/following-sibling axis. Try this:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" >
<xsl:output method="xml" indent="yes"/>
<xsl:key name="Date" match="DocumentElement/Records/date" use="substring(.,1,4)"/>
<xsl:template match="/">
<ul>
<xsl:for-each select="DocumentElement/Records/date[generate-id() = generate-id(key('Date', substring(.,1,4))[1])]">
<li>
<a href="{concat('?archive=',substring(.,1,4))}">
<xsl:value-of select="substring( ., 1, 4)"/>
</a>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="#..OfferLetter.xslt"?>
<Doc>
<assembly>
<Heading>Offer Letter</Heading>
</assembly>
<RefNo>Ref No:0007</RefNo>
<Date></Date>
<to>To</to>
<name></name>
<city></city>
<dear>
<a>Dear Mr.</a>
<name></name>
</dear>
<p1>
<a1>
With reference to your application and the subsequent personal interview attended by you,
we are pleased to inform that you have been selected for employment in ..
(hereinafter referred to as “Company”).
We are delighted to make you the following offer for employment.
</a1>
</p1>
</Doc>
here my xslt code for that..
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:template match="/">
<html>
<body>
<h2 style ="text-align: center;">Offer Letter</h2>
<h3 style="text-align:Right; margin-right: 110px;">Ref No:K070813</h3>
<h3 style="text-align:Right ; margin-right: 224px; ">Date:</h3>
<h3 style="text-align:Left; margin-left: 50px;">To</h3>
<h3 style="text-align:Left; margin-left: 50px;">MR.</h3>
<h3 style="text-align:Left; margin-left: 50px;">Hyderabad</h3>
<br></br>
<h3 style="text-align:Left; margin-left: 50px;">Dear Mr.</h3>
<xsl:for-each select="Doc/p1">
<h3 style="text-align:Left; margin-left: 50px;">
<xsl:value-of select="a1"/>
</h3>
</xsl:for-each>
</body>
</html>
here my TransformHRML() code
public static void TransformXML()
{
// Create a resolver with default credentials.
XmlUrlResolver resolver = new XmlUrlResolver();
resolver.Credentials = System.Net.CredentialCache.DefaultCredentials;
// transform the OfferLetter.xml file to HTML
XslTransform transform = new XslTransform();
// load up the stylesheetfile:
transform.Load(HttpContext.Current.Server.MapPath("OfferLetter.xslt"));
// perform the transformation
transform.Transform(#"..\OfferLetter.xml", #"..\OfferLetter.html", resolver);
// transform the OfferLetter.xml file to comma delimited format
// load up the stylesheet
transform.Transform(HttpContext.Current.Server.MapPath("OfferLetter.xslt"), #"..\OfferLetter.html",resolver);
}
please help me..
There are a bunch of close-tag issues, and the extraneous # in the xml file as picked up by Tim.
After tidying these up, your xslt works, but I would push you to use apply-templates and not for-each:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="OfferLetter.xslt"?>
<Doc>
<assembly>
<Heading>Offer Letter</Heading>
</assembly>
<RefNo>Ref No:0007</RefNo>
<!--etc-->
<p1>
<a1>
With reference to your application and the subsequent , ...
</a1>
</p1>
<p1>
<a1>
Another Paragraph
</a1>
</p1>
</Doc>
With the XSLT:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl">
<xsl:template match="/">
<html>
<body>
<!--Did you mean to hard code these fields? -->
<h2 style ="text-align: center;">
<xsl:value-of select="assembly/Heading"/>
</h2>
<h3 style="text-align:Right; margin-right: 110px;">
<xsl:value-of select="assembly/RefNo"/>
</h3>
<!--etc-->
<xsl:apply-templates select="Doc/p1">
</xsl:apply-templates>
</body>
</html>
</xsl:template>
<xsl:template match="p1">
<h3 style="text-align:Left; margin-left: 50px;">
<xsl:value-of select="a1"/>
</h3>
</xsl:template>
</xsl:stylesheet>
I am trying to create a super generic XSLT that basically can only count on the table & row elements being there. I have the following sample XML I am trying to make an XSLT for:
<?xml version="1.0" encoding="UTF-8"?>
<table>
<row>
<id>5311</id>
<status>Active</status>
<id_vendor>Verizon</id_vendor>
<mobile_number>555123456</mobile_number>
</row>
<row>
<id>5312</id>
<status>Inactive</status>
<id_vendor>Sprint</id_vendor>
<mobile_number>555123457</mobile_number>
</row>
<row>
<id>5313</id>
<status>Active</status>
<id_vendor>ATT</id_vendor>
<mobile_number>555123458</mobile_number>
</row>
</table>
The problem is that I do not know what the fields are going to end up being (id, status, id_vendor, mobile_number, etc. are all subject to change.
I want to make pleasant to look at view such as:
<div style="background-color:#E3CA87;padding:.2em">
<div style="background-color:#F1E2BB;padding:.2em">
<div>id: x<div>
<div>status: active<div>
<div>id_vendor: Verizon<div>
<div>mobile_number: 555123456<div>
<div>
<div>
Here is what I have so far.. but I can't get the anonymous elements going right:
<?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<body style="background-color:#eee;font-size:12pt;font-family:Arial;">
<xsl:for-each select="table/row">
<div style="background-color:#eee;padding:.5em">
<xsl:for-each select="/*">
<div style="background-color:#E3CA87;padding:.2em;border: 1px solid black">
<xsl:for-each select="./*">
<div style="background-color:#F1E2BB;padding:.2em">
<xsl:value-of select ="name(./*)"/>:
<xsl:value-of select="*" />
</div>
</xsl:for-each>
</div>
</xsl:for-each>
</div>
</xsl:for-each>
</body>
</html>
Close... but it was actually a little differnt.. just figured it out for anyone that want's to know:
<?xml version="1.0" encoding="UTF-8"?>
<html xsl:version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<body style="background-color:#eee;font-size:12pt;font-family:Arial;">
<xsl:for-each select="table/row">
<div style="background-color:#eee;padding:.5em">
<xsl:for-each select=".">
<div style="background-color:#E3CA87;padding:.2em;border: 1px solid black">
<xsl:for-each select=".">
<xsl:for-each select="./*">
<div style="background-color:#F1E2BB;padding:.2em">
<xsl:value-of select="concat(local-name(.), ': ', .)" />
</div>
</xsl:for-each>
</xsl:for-each>
</div>
</xsl:for-each>
</div>
</xsl:for-each>
</body>
</html>
Use relative paths e.g. <xsl:for-each select="*"> instead of <xsl:for-each select="/*">. Then I think you want to drop the inner for-each and simply replace it with
<div style="background-color:#F1E2BB;padding:.2em">
<xsl:value-of select="concat(local-name(), ': ', .)" />
</div>
Any help much appreciated on this.
I'd like to remove certain nodes from being published in a feed from an external xml file, which I've styled with xslt. Here is the feed:http://www.wcwg.info/feeds/localevents.aspx?a=00392&p=CM159EH&m=20.
The nodes I would like to remove are:
Local Events posted to WhereCanWeGo.com.00392CM15
9EH31/10/1007/11/1010001111111111111111111031
October
2010http://www.wherecanwego.com/events/signin.aspxww.wherecanwego.com/events/signin.aspx
Could anybody be kind enough to direct me how to remove these initial nodes (parameters)? They are the postcode, account number, feed URL etc.
I'm desperate to get this finished, but it's the final hurdle! Many thanks in advance for anyone who responds...
The stylesheet (fragment)
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="item">
<div class="local_events">
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="Venue"/>
<xsl:apply-templates select="Times"/>
<xsl:apply-templates select="Dates"/>
<xsl:apply-templates select="DetailsURL"/>
</div><div style="height:1px;border-bottom:1px dotted #cfcfcf;"></div>
</xsl:template>
<xsl:template match="title">
<h2><a class="title" target="_blank" rel="nofollow" href="{../DetailsURL}"><xsl:value-of select="."/></a></h2>
</xsl:template>
<xsl:template match="Venue">
<span>Location: </span>
<xsl:value-of select="."/>
<br />
</xsl:template>
<xsl:template match="Times">
<span>Details: </span>
<xsl:value-of select="."/>
<br />
</xsl:template>
<xsl:template match="Dates">
<span>Dates: </span>
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="DetailsURL">
<a style="font-weight:normal;margin-left:0.5em;" target="_blank" rel="nofollow" href="{.}"><xsl:text>Full details...</xsl:text></a>
</xsl:template>
From your poorly formulated question and analyzing the feed, it seems that you want to get rid of all children of the top (LocalEvents) node that are not named item.
This transformation:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*/*[not(self::item)]"/>
</xsl:stylesheet>
when applied on the provided feed (http://www.wcwg.info/feeds/localevents.aspx?a=00392&p=CM159EH&m=20), produces the wanted result.
Do note: how the wanted elements are deleted (not processed, ignored) by an empty template matching them and overriding the identity rule that is used to copy the rest of the nodes "as-is".
If you already use an XSLT stylesheet that does not do exactly what you want then please post the stylesheet or a link to it.
[edit]
In your posted stylesheet change
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
to
<xsl:template match="/">
<xsl:apply-templates select="//item"/>
</xsl:template>
This has now been corrected to the following which now works, for anyone else in the same situation:
<xsl:template match="/">
<xsl:apply-templates select="/LocalEvents/item"/>
</xsl:template>
<xsl:template match="item">
<div class="local_events">
<xsl:apply-templates select="title"/>
<xsl:apply-templates select="Venue"/>
<xsl:apply-templates select="Times"/>
<xsl:apply-templates select="Dates"/>
<xsl:apply-templates select="DetailsURL"/>
</div><div style="height:1px;border-bottom:1px dotted #cfcfcf;"></div>
</xsl:template>
<xsl:template match="title">
<h2><a class="title" target="_blank" rel="nofollow" href="{../DetailsURL}"><xsl:value-of select="."/></a></h2>
</xsl:template>
<xsl:template match="Venue">
<span>Location: </span>
<xsl:value-of select="."/>
<br />
</xsl:template>
<xsl:template match="Times">
<span>Details: </span>
<xsl:value-of select="."/>
<br />
</xsl:template>
<xsl:template match="Dates">
<span>Dates: </span>
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="DetailsURL">
<a style="font-weight:normal;margin-left:0.5em;" target="_blank" rel="nofollow" href="{.}"><xsl:text>Full details...</xsl:text></a>
</xsl:template>
</xsl:stylesheet>
Other approuch. This stylesheet:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:preserve-space elements="Times"/>
<xsl:template match="text()"/>
<xsl:template match="item">
<div class="local_events">
<xsl:apply-templates/>
</div>
<div style="height:1px;border-bottom:1px dotted #cfcfcf;"></div>
</xsl:template>
<xsl:template match="title">
<h2>
<a class="title" target="_blank" rel="nofollow" href="{../DetailsURL}">
<xsl:value-of select="."/>
</a>
</h2>
</xsl:template>
<xsl:template match="Venue">
<span>Location: </span>
<xsl:value-of select="."/>
<br />
</xsl:template>
<xsl:template match="Times">
<span>Details: </span>
<xsl:value-of select="."/>
<br />
</xsl:template>
<xsl:template match="Dates">
<span>Dates: </span>
<xsl:value-of select="."/>
</xsl:template>
<xsl:template match="DetailsURL">
<a style="font-weight:normal;margin-left:0.5em;" target="_blank" rel="nofollow" href="{.}">
<xsl:text>Full details...</xsl:text>
</a>
</xsl:template>
</xsl:stylesheet>
Note: When doing a one to one transformation in the same hierarchy, it's enough to declare the rules for specific elements in input source and to overwrite the built-in rule for text node (output the string value) with an empty rule.