I need help converting an XSLT 1.0 file to 2.0 (so I can use the XSLT 2.0 replace() function call).
I've Googled, searched different books and SO with no success. I tried changing version="1.0" to 2.0 and changing html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en" to simply html but this all just results in XSLTProcessor errors.
Any help is greatly appreciated. Thanks in advance.
Here is my XSLT:
<?xml version="1.0" encoding="ISO-8859-1" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml" version="1.0">
<xsl:output method="xml" omit-xml-declaration="yes" indent="no"
doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"
doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN" encoding="ISO-8859-1" />
<xsl:template match="/">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<xsl:element name="meta">
<xsl:attribute name="name">description</xsl:attribute>
<xsl:attribute name="content"><xsl:value-of select="EventList/title"/></xsl:attribute>
</xsl:element>
<xsl:element name="link"><xsl:attribute name="rel">alternate</xsl:attribute><xsl:attribute name="type">application/rss+xml</xsl:attribute><xsl:attribute name="title">RSS</xsl:attribute><xsl:attribute name="href"><xsl:value-of select="EventList/rssURL"/></xsl:attribute></xsl:element>
</head>
<body>
<xsl:apply-templates select="EventList" />
</body>
</html>
</xsl:template>
<xsl:template match="EventList">
<xsl:choose>
<xsl:when test="Event">
<xsl:apply-templates select="Event"/>
</xsl:when>
<xsl:otherwise>
<div class="eventItem">
<div class="eventItemText">
<p>There are currently no events posted for this category.</p>
</div>
</div>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- List -->
<xsl:template match="Event">
<li>
<!-- Title -->
<xsl:if test="eventStatus = 2"><xsl:value-of select="eventStatusString"/> - </xsl:if>
<xsl:element name="a"><xsl:attribute name="href">http://events.stanford.edu/e/e/?d=<xsl:value-of select="replace(detailpath,'/events/','')"/></xsl:attribute><xsl:attribute name="id"><xsl:value-of select="eventID"/></xsl:attribute><xsl:attribute name="rel">external</xsl:attribute>
<xsl:value-of select="title" disable-output-escaping="yes"/>
</xsl:element>
<!-- Date and time -->
<xsl:element name="a"><xsl:attribute name="href">http://events.stanford.edu/e/details.php?detailpath=<xsl:value-of select="detailpath"/></xsl:attribute><xsl:attribute name="rel">external</xsl:attribute>
<xsl:choose>
<xsl:when test="repeatRuleID > 0">
Ongoing <xsl:value-of select="repeatRuleText"/> from <xsl:value-of select="beginDate"/> through <xsl:value-of select="repeatUntilDate"/>.
<xsl:if test="repeatRuleID=99">See details for exact dates and times.</xsl:if>
</xsl:when>
<xsl:otherwise>
<xsl:if test="string(beginDay)"><xsl:value-of select="beginDay"/>, </xsl:if>
<xsl:value-of select="beginDate"/>.
</xsl:otherwise>
</xsl:choose>
<xsl:if test="repeatRuleID!=99">
<xsl:if test="string(beginTime)">
<xsl:text disable-output-escaping="yes"></xsl:text><xsl:value-of select="beginTime"/>.
</xsl:if>
</xsl:if>
</xsl:element>
<!-- Location -->
<xsl:element name="a"><xsl:attribute name="href">http://events.stanford.edu/e/details.php?detailpath=<xsl:value-of select="detailpath"/></xsl:attribute><xsl:attribute name="rel">external</xsl:attribute>
<xsl:value-of select="locationText"/>
</xsl:element>
</li>
</xsl:template>
</xsl:stylesheet>
In addition to changing the version attribute to '2.0', you need to feed your XSLT 2.0 code to an XSLT 2.0 processor.
At present, some of the XSLT 2.0 processors I use are:
Saxon 9.x
XQSharp 2.0
AltovaXML (XMLSpy)
Do note that an existing XSLT 1.0 code may behave differently under XSLT 2.0 -- the most obvious differences are that <xsl:value-of> no longer produces the string value of only the first node from a node-set, and that in XSLT 2.0 the dreaded RTF type has been eliminated, so no xxx:node-set() extension function is needed/provided.
You should also check the non normative XSLT 2.0 Appendix J Changes from XSLT 1.0 .
This section lists all known cases
where a stylesheet that was valid
(produced no errors) under XSLT 1.0,
and whose behavior was fully specified
by XSLT 1.0, will produce different
results under XSLT 2.0.
While you're converting the code, you should get rid of those ugly disable-output-escaping="yes" attributes. They are almost certainly not wanted. The use of this attribute usually indicates that it was written by a novice with a poor understanding of the language. This also applies to the use of verbose constructs like
<xsl:element name="a"><xsl:attribute name="href">http://events.stanford.edu/e/e/?d=<xsl:value-of select="replace(detailpath,'/events/','')"/></xsl:attribute><xsl:attribute name="id"><xsl:value-of select="eventID"/></xsl:attribute><xsl:attribute name="rel">external</xsl:attribute>
<xsl:value-of select="title" disable-output-escaping="yes"/>
</xsl:element>
that could be replaced by the much more readable
<a href="http://events.stanford.edu/e/e/?d={replace(detailpath,'/events/','')}"
id="{#eventID}" rel="external">
<xsl:value-of select="title"/>
</a>
Generally, some refactoring is long overdue for this code.
Related
I just need some help on basic feature of XSL.
I would like to display a sum of amounts previously computed. But I do not know how to do it.
For information the XSL must work with XSLT 1.0, technical limitation on my side.
For instance here is my xml.
<A>
<amount>10</amount>
<rate>4</rate>
</A>
<A>
<amount>-21</amount>
<rate>2</rate>
</A>
<B>
<amount>8</amount>
<rate>1</rate>
</B>
<C>
<amount>7</amount>
<rate>32</rate>
</C>
and I would like to display the sum of each amount multiplied by each associated rate within a Total element.
<Total value="230">
<PositiveTotal>
272
</PositiveTotal>
<NegativeTotal>
-42
</NegativeTotal>
</Total>
I have no idea how to do it.
Thanks in advance
Regards,
One of possible multiple solutions. It will give you an idea, how to solve this.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="root">
<xsl:variable name="positiveTotal">
<xsl:call-template name="sum">
<xsl:with-param name="items" select="*[not(starts-with(amount,'-') or starts-with(rate, '-'))]"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="negativTotal">
<xsl:call-template name="sum">
<xsl:with-param name="items" select="*[starts-with(amount,'-') or starts-with(rate, '-')]"/>
</xsl:call-template>
</xsl:variable>
<Total value="{$positiveTotal + $negativTotal}">
<PositivTotal>
<xsl:value-of select="format-number($positiveTotal, '0')"/>
</PositivTotal>
<NegativeTotal>
<xsl:value-of select="format-number($negativTotal, '0')"/>
</NegativeTotal>
</Total>
</xsl:template>
<xsl:template name="sum">
<xsl:param name="items" />
<xsl:param name="total" select="0" />
<xsl:choose>
<xsl:when test="not($items)">
<xsl:value-of select="$total"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="sum">
<xsl:with-param name="items" select="$items[position() > 1]" />
<xsl:with-param name="total"
select="$total + ($items[1]/amount * $items[1]/rate)" />
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
!! Change match="root" to your root-node! Given source-xml is not valid.
There are already many sum-questions! See the Related Box on your right side of screen.
This question has been asked many times and following the links to similar searches on SO should give you lots of ideas.
Computing the sum of computed values in XSLT 2.0 is trivial, but in XSLT 1.0 it isn't easy because there's no such data type in its data model as a set of numbers (sum() only works over a set of nodes). Possible solutions include:
(a) a recursive template call which supplies the running total as a parameter to the template, adds the next value, then calls the template again to process the rest of the list with the new running total
(b) a multiphase transformation where the computed values are placed in XML nodes during one phase, and summed using the sum() function in a second phase
(c) use of the FXSL library which uses xsl:apply-templates to simulate higher-order functions and then provides a fold mechanism which can be specialised to implement summation.
(d) calling out to extension functions in a procedural programming language
(e) upgrading to XSLT 2.0.
I would suggest you do it this way:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
<!-- first pass -->
<xsl:variable name="summands-rtf">
<xsl:for-each select="*">
<value>
<xsl:value-of select="amount * rate" />
</value>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="summands" select="exsl:node-set($summands-rtf)/value" />
<!-- output -->
<Total value="{sum($summands)}">
<PositiveTotal>
<xsl:value-of select="sum($summands[. > 0])" />
</PositiveTotal>
<NegativeTotal>
<xsl:value-of select="sum($summands[. < 0])" />
</NegativeTotal>
</Total>
</xsl:template>
</xsl:stylesheet>
When applied to a well-formed XML input (with a single root element):
XML
<root>
<A>
<amount>10</amount>
<rate>4</rate>
</A>
<A>
<amount>-21</amount>
<rate>2</rate>
</A>
<B>
<amount>8</amount>
<rate>1</rate>
</B>
<C>
<amount>7</amount>
<rate>32</rate>
</C>
</root>
the result will be:
<?xml version="1.0" encoding="UTF-8"?>
<Total value="230">
<PositiveTotal>272</PositiveTotal>
<NegativeTotal>-42</NegativeTotal>
</Total>
Im using doctype: XHTML Mobile Profile 1.2, XML version="1.0 and Content-Type "application/xhtml+xml"
Is it possible to disable or prevent <cite> tag appearing within RSS feed, Due to the fact that I keep getting this error on the Page itself.
error on line 24 at column 70: expected '>'
Below is a rendering of the page up to the first error.
I am using an external feed from another site, which is not mine to control or edit.
I am using an XSLT and ColdFusion file to read the external RSS file, and display it the way I want within my XSLT, I already have in place disable-output-escaping="yes" to prevent lose code showing up within the feed. My XSLT works when this tag is not there
I have tried to get around it, but no luck. Is it actually possible to do this?
CFM
<cfcontent type="application/xhtml+xml" reset="yes">
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.2//EN" "http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd">
<cfhttp method="Get" url="http://www.animenewsnetwork.com/news/rss.xml">
<cfset xmlInput = CFHTTP.FileContent>
<cfset MyXslFile = Expandpath("animenewsrss.xsl")>
<cffile action="READ" variable="xslInput" file="#MyXslFile#">
<cfset xmlOutput = XMLTransform(xmlInput, xslInput)>
<cfoutput>#xmloutput#</cfoutput>
XSLT
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes" />
<xsl:template match="rss/channel">
<xsl:element name="html">
<xsl:element name="head">
<xsl:element name="title">Anime News</xsl:element>
</xsl:element>
<xsl:element name="body">
<xsl:element name="div"><xsl:attribute name="id"><xsl:value-of select="'hstyle'"/></xsl:attribute>Media Events UK - Anime News</xsl:element>
<xsl:element name="div"><xsl:attribute name="id"><xsl:value-of select="'nstyle'"/>
</xsl:attribute><xsl:element name="a"><xsl:attribute name="href">index.cfm</xsl:attribute>Home</xsl:element> -
<xsl:element name="a"><xsl:attribute name="href">listings.cfm</xsl:attribute>Listings</xsl:element> -
<xsl:element name="a"><xsl:attribute name="href">venue.cfm</xsl:attribute>Venues</xsl:element>
</xsl:element>
<xsl:apply-templates select="item[position() < 6]" />
</xsl:element>
</xsl:element>
</xsl:template>
<xsl:template match="item[position() < 6]">
<div class="rsstyle">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="link"/>
</xsl:attribute>
<xsl:value-of select="title" />
</xsl:element>
<xsl:element name="div">
<xsl:value-of select="pubDate" />
</xsl:element>
<xsl:element name="div">
<xsl:value-of select="concat(substring(description, 1, 50), '...')" disable-output-escaping="yes"/>
</xsl:element>
</div>
</xsl:template>
</xsl:stylesheet>
With this line
<xsl:value-of select="concat(substring(description, 1, 50), '...')" disable-output-escaping="yes"/>
you cut the content of <description>, which contains cite elements in some cases. This leads to lines like the following in your result HTML:
<div><cite>Ni No Kuni</cite>, <cite>Tales of Xillia</ci...</div>
As you can see, the cite element is not closed properly anymore, because you cut the content of the description element at 50 characters. If you counted the characters, you'd notice that the content of description stops at 50, then "..." is inserted.
If you describe your intent behind applying substring to decription elements, SO can help you find a good alternative to this.
My guess is that you need to take into account the possibility that description contains not only text, but also elements (like cite). Then, it makes sense to use substring only on the text content of description, like this:
concat(substring(description/text(),1,50),'...')
Then go on to catch the child elements of description, e.g. in a separate template:
<xsl:template match="cite[parent::description]">
<!--Deal with cite elements-->
</xsl:template>
EDIT: I adapted your stylesheet to process cite elements as children of description. There are 2 additional templates that process text nodes and cite nodes, both being children of description.
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" omit-xml-declaration="yes" />
<xsl:template match="rss/channel">
<!--I left this template unchanged!-->
</xsl:template>
<xsl:template match="item[position() < 6]">
<div class="rsstyle">
<xsl:element name="a">
<xsl:attribute name="href">
<xsl:value-of select="link"/>
</xsl:attribute>
<xsl:value-of select="title" />
</xsl:element>
<xsl:element name="div">
<xsl:value-of select="pubDate" />
</xsl:element>
<xsl:element name="div">
<xsl:apply-templates select="description"/>
</xsl:element>
</div>
</xsl:template>
<xsl:template match="description">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="text()[parent::description]">
<xsl:copy/>
</xsl:template>
<xsl:template match="cite[parent::description]">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
I am just getting into xslt transformation and after going through a tutorial I tried doing some code in visual studio 2008. I tried the following code after linking the xml document I needed as input:
<?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:template match="/">
<xsl:copy>
<xsl:element name="entry">
<xsl:attribute name="published" >
<xsl:value-of select="entry/published"/>
</xsl:attribute>
<xsl:attribute name="title" >
<xsl:value-of select="title"/>
</xsl:attribute>
<xsl:attribute name="summary" >
<xsl:value-of select="summary"/>
</xsl:attribute>
</xsl:element>
</xsl:copy>
</xsl:template>
here is a sample of the xml file:
<entry xmlns:gnip="http://www.p.com/schemas/2010" xmlns="http://www.w3.org/2005/Atom">
<id>tag:search,2005:38587000730689536</id>
<published>2011-02-18T13:13:52Z</published>
<updated>2011-02-18T13:13:52Z</updated>
<title>nachopego (J Ignacio Peña G.) posted a note</title>
<summary type="html">Truculencia: en Nayarit no nada mas
el engrudo se hace bolas</summary>
<category term="StatusPosted" label="Status Posted"/>
<category term="NotePosted" label="Note Posted"/>
<link rel="alternate"
type="text/html" href="http://nachopego/statuses/38587000730689536"/>
This is the Most FAQ in the xpath and xslt tags: XPath expressions against an XML document with a default namespace.
Just search for "xpath default namespace" and you will find many good answers.
Solution:
Add a namespace declaration in the XSLT stylesheet for the default namespace of the XML document. Use the prefix (say) "x:" in this declaration.
In any XPath expression that references an element by name, prefix every name with the "x:" prefix.
Your code becomes:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:x="http://www.w3.org/2005/Atom" >
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<xsl:copy>
<xsl:element name="entry">
<xsl:attribute name="published" >
<xsl:value-of select="x:entry/x:published"/>
</xsl:attribute>
<xsl:attribute name="title" >
<xsl:value-of select="x:title"/>
</xsl:attribute>
<xsl:attribute name="summary" >
<xsl:value-of select="x:summary"/>
</xsl:attribute>
</xsl:element>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
and now it produces some output.
Explanation:
Xpath always treats unprefixed names as belonging to "no namespace". Thus if an expression contains the name someName, XPath tries to find an element with the name someName that belongs to "no namespace" and fails, because all the elements in the document belong to its non-empty default namespace.
The solution (as the one above) is to refer to the names using a prefixed name, where the prefix is bound exactly to the default namespace of the XML document.
By the way, this code
<xsl:element name="entry">
<xsl:attribute name="published" >
<xsl:value-of select="x:entry/x:published"/>
</xsl:attribute>
<xsl:attribute name="title" >
<xsl:value-of select="x:title"/>
</xsl:attribute>
<xsl:attribute name="summary" >
<xsl:value-of select="x:summary"/>
</xsl:attribute>
</xsl:element>
can be written much more legibly as
<entry published="{x:entry/x:published}"
title="{x:title}"
summary="{x:summary}"/>
I'm trying to conditionally display the content of HTML page depending if a document being generated for a recognised company or not.
However, the transformation doesn't work and I can't understand why :( I use MSXML3.0 as transformer and oXygen as IDE, which gives the errors I presented below.
What I do is to construct a long string of all recognised companies (default and extra if any). I then split them into <token> elements that are stored in the $companiesKnownList variable. To determine if a company is in that list I count how many times it occurs:
count($companiesKnownList/token[normalize-space(.) = $productName]) < 1
If it's less than 1, then the company doesn't appear in the $companiesKnownList variable and therefore is not recognized. Otherwise, if it appears in the $companiesKnownList variable once or more times it is a recognized company. Nevertheless, this is where it breaks and displays the following error:
Description: Code: 0x80004005
Description: The XSL processor stack has overflowed - probable cause is infinite template recursion.
Description: The transformer process ended with code: 1
I've noticed that if my XML has got a recognised company, ex #ProductName="ski" then transformation fails with stack overflow. If I have an unrecognized company, ex #ProductName="bla" the transformation works and text that it isn't a recognized company is displayed.
I don't understand what's going wrong with valid companies. I would be more than grateful if you could help me out. I have been staring at it for a day now...without any progress :S
Thanks!
Here is my stylesheet:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:msxsl="urn:schemas-microsoft-com:xslt"
xmlns:str="http://exslt.org/strings"
extension-element-prefixes="msxsl str"
version="1.0">
<!-- Taken from http://www.exslt.org/str/functions/tokenize/index.html -->
<xsl:import href="str.tokenize.template.xsl"/>
<!-- normalize and lowcase product name -->
<xsl:variable name="productName"
select="normalize-space(translate(/Doc/#ProductName, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'))"/>
<!-- default recognised companies for all docs -->
<xsl:variable name="defaultRecognisedCompanies" select="'ski, holiday, summer trips'"/>
<!-- Determine what companies to generate a doc for -->
<xsl:variable name="companiesKnownListRaw">
<xsl:call-template name="recognisedCompanies"/>
</xsl:variable>
<xsl:variable name="companiesKnownList" select="msxsl:node-set($companiesKnownListRaw)"/>
<!-- Lists recognised companies for a document to be generated for -->
<xsl:template name="recognisedCompanies">
<xsl:call-template name="recognisedCompaniesListForDocument"/>
</xsl:template>
<xsl:template name="recognisedCompaniesListForDocument">
<xsl:param name="defaultCompanies" select="$defaultRecognisedCompanies"/>
<xsl:param name="isUseDefaultsCompanies" select="true()"/>
<xsl:param name="extraCompanies" select="''"/>
<xsl:variable name="allCompaniesRaw">
<xsl:call-template name="str:tokenize">
<xsl:with-param name="string">
<xsl:choose>
<!-- keep default companies -->
<xsl:when test="$isUseDefaultsCompanies = 'true'">
<xsl:value-of select="concat($defaultCompanies, ', ', $extraCompanies)"/>
</xsl:when>
<!-- discard default companies -->
<xsl:otherwise>
<xsl:value-of select="$extraCompanies"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="delimiters" select="','" />
</xsl:call-template>
</xsl:variable>
<!-- Normalize token's value and discard empty values -->
<xsl:for-each select="msxsl:node-set($allCompaniesRaw)/token">
<xsl:if test="normalize-space(.) != ''">
<token>
<xsl:value-of select="normalize-space(.)"/>
</token>
</xsl:if>
</xsl:for-each>
</xsl:template>
<!-- Construct HTML doc. Display appropriate message for a company if it's recognized or not -->
<xsl:output method="html" doctype-public="-//W3C//DTD HTML 4.01 Transitional//EN"
doctype-system="http://www.w3.org/TR/html4/loose.dtd" encoding="UTF-8" indent="yes"/>
<xsl:template match="/Doc">
<html>
<xsl:choose>
<!-- Not recognised company -->
<!-- There is something wrong with the count conditions, and I don't understand what :( -->
<xsl:when test="count($companiesKnownList/token[normalize-space(.) = $productName]) < 1">
<body>
<div align="center">
This type of company is NOT recognised for this document.
</div>
</body>
</xsl:when>
<!-- Recognised company -->
<xsl:otherwise>
<body>
<div align="center">
This type of company is recognised for this document.
</div>
</body>
</xsl:otherwise>
</xsl:choose>
</html>
</xsl:template>
</xsl:stylesheet>
XML is something simple like:
In this example, ski is recognized company, but transformation fails.
<?xml version="1.0" encoding="UTF-8"?>
<Doc ProductName="ski" />
In this example, bla is not a recognized company and transformation succeeds with displaying text: "This type of company is NOT recognised for this document."
<?xml version="1.0" encoding="UTF-8"?>
<Doc ProductName="bla" />
You need to add the implementation of your named template str:tokenize. Check Jeni Tennison implementation at http://www.exslt.org/str/functions/tokenize/str.tokenize.template.xsl
Then, add this as stylesheet top element, with correct href:
<xsl:include href="str.tokenize.template.xsl"/>
With that changes (and closing your last template) with this input:
<Doc ProductName="ski" />
Ouput:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<div align="center">
This type of company is recognised for this document.
</div>
</body>
</html>
MSXML (any version) does not support EXSLT -- and the XSLT processor produces an error message.
Could you, please, correct the question so that only true information is present?
Is there any replacement for saxon:if
and saxon:before functions in XSLT 2.0 / XPath 2.0?
I have code like this:
<xsl:variable name="stop"
select="(following-sibling::h:h1|following-sibling::h:h2)[1]" />
<xsl:variable name="between"
select="saxon:if($stop,
saxon:before(following-sibling::*, $stop),
following-sibling::*)" />
Idea is that between variable should contain all elements between current node and next h1 or h2 element (stored in stop variable), or all remaining elements, if there is no next h1 or h2.
I'd like to use this code in new XSLT 2.0 template, and I am looking for replacement for saxon:if and saxon:before.
saxon.if(A, B, C) is now equivalent to if (A) then B else C in XPath 2.0
Here is my solution:
<xsl:variable
name="stop"
select="(following-sibling::h:h1|following-sibling::h:h2)[1]" />
<xsl:variable name="between">
<xsl:choose>
<xsl:when test="$stop">
<xsl:sequence select="following-sibling::*[. << $stop]" />
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="following-sibling::*" />
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
It uses <xsl:sequence> and << operator (encoded as <<), from XSLT 2.0 / XPath 2.0.
It's not as short as original version, but it doesn't use saxon extensions anymore.
You also could use just one expression in XSLT/XPath 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="text()"/>
<xsl:template match="p[position()=(1,3,4)]">
<xsl:copy-of select="following-sibling::*
[not(self::h2|self::h1)]
[not(. >>
current()
/following-sibling::*
[self::h2|self::h1][1])]"/>
</xsl:template>
</xsl:stylesheet>
With this input:
<html>
<p>1</p>
<p>2</p>
<h2>Header</h2>
<p>3</p>
<h1>Header</h1>
<p>4</p>
<p>5</p>
</html>
Output:
<p>2</p><p>5</p>