Recoverable error while running XSL - xslt-2.0

XSL:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ve="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" exclude-result-prefixes="wp wne w10 w ve o r m v" version="2.0">
<xsl:output method="text"/>
<xsl:param name="styleName"/>
<xsl:template match="w:p">
<xsl:apply-templates/><xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="w:r[not
((parent::w:hyperlink[#w:anchor[matches(.,concat('^(',$styleName,')')),'i']]))]">
<xsl:value-of select="replace(., '.', '＀')"/>
</xsl:template>
</xsl:stylesheet>
While processing the above XSL, I am getting the below error,
Recoverable Error:
Recoverable error on line 11
FORG0006: An error occurred matching pattern {w:r[not
((parent::w:hyperlink[#w:anchor[matches(.,concat('^(',$styleName,')')),'i']]))]}:
Effective boolean value is not defined for a sequence of two or more items starting with a boolean
Please Help. I am not able to figure out this.

The problem is with 'i' [modifier added to perform case-insensitive search], It is specified after the matches() method.

Related

XSLT 3.0 Streaming (Saxon) facing error "There is more than one consuming operand" when I use two different string functions within same template

Here is my sample input xml
<?xml version="1.0" encoding="UTF-8"?>
<Update xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Request>
<List>
<RequestP><ManNumber>3B4</ManNumber></RequestP>
<RequestP><ManNumber>8T7_BE</ManNumber></RequestP>
<RequestP><ManNumber>3B5</ManNumber></RequestP>
<RequestP><ManNumber>5E9_BE</ManNumber></RequestP>
<RequestP><ManNumber>9X6</ManNumber></RequestP>
</List>
</Request>
</Update>
and xslt
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="3.0" exclude-result-prefixes="#all">
<xsl:output method="xml" omit-xml-declaration="no" indent="yes" />
<xsl:mode streamable="yes" />
<xsl:template match="List/RequestP/ManNumber">
<ManNumber>
<xsl:value-of select="replace(.,'_BE','')" />
</ManNumber>
<xsl:if test="contains(.,'_BE')">
<ManDescrip>BE</ManDescrip>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
I am getting below error for above xslt, I am using Saxon 11.2 version
Template rule is not streamable
* There is more than one consuming operand: {<ManNumber {xsl:value-of}/>} on line 6, and {if(fn:contains(...)) then ... else ...} on line 9
The xslt works fine if I use either "replace" or "contains" but not both within same template.
Streamed processing, if you have needs (huge input documents in the size of gigabytes) to use it, requires you to limit your XSLT to streamable code, that means you can for instance make a copy of that element and processed only that small element node as a complete in memory element in a different mode
<xsl:template match="List/RequestP/ManNumber">
<xsl:apply-templates select="copy-of(.)" mode="grounded"/>
</xsl:template>
<xsl:template name="grounded" match="ManNumber">
<ManNumber>
<xsl:value-of select="replace(.,'_BE','')" />
</ManNumber>
<xsl:if test="contains(.,'_BE')">
<ManDescrip>BE</ManDescrip>
</xsl:if>
</xsl:template>

How do I split and print values in xslt?

I want to create an xslt(version 2) where value can be split with delimeter ':' and print only first part of split and store the second part into a variable. The values have to be passed to a 'student' tag. Following are the values that are fetched from db
Adam:101
Brad:110
Chad:111
Expected output:
Adam
Brad
Chad
and values 101, 110 and 111 have to stored into a variable.
Please also provide a link where xslt2.0 tutorial is available in detail.
Simply you can use fn:tokenize() to achieve the output:
Assume input:
<student>Adam:101 Brad:110 Chad:111</student>
XSLT:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="2.0">
<xsl:output indent="yes"/>
<xsl:template match="/">
<students>
<xsl:apply-templates/>
</students>
</xsl:template>
<xsl:template match="student">
<xsl:for-each select="tokenize(., ' ')">
<student variable="{substring-after(., ':')}">
<xsl:value-of select="substring-before(., ':')"/>
</student>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
OUTPUT:
<?xml version="1.0" encoding="UTF-8"?>
<students>
<student variable="101">Adam</student>
<student variable="110">Brad</student>
<student variable="111">Chad</student>
</students>
Link: https://xsltfiddle.liberty-development.net/gVrvcxx

How can we remove blank line without strip-space and indent XSLT2.0

I am trying remove blank lines without stripping spaces and indentation, because my requirement is indented XML. Can anyone help me, please?
Input XML
<?xml version="1.0" encoding="UTF-8"?>
<Export>
<bio id="b0001">
<p>Maciej</p>
</bio>
<funding-group>
<award-group>
<funding-source>
<named-content content-type="funder-name">Narodowe</named-content>
<named-content content-type="funderidentifier">501100004281</named-content>
</funding-source>
<award-id>/19/B/HS4/</award-id>
<award-id>3</award-id>
</award-group>
</funding-group>
</Export>
Expected Result
<?xml version="1.0" encoding="UTF-8"?>
<Export>
<bio id="b0001">
<p>Maciej</p>
</bio>
<funding-group>
<award-group>
<funding-source>
<named-content content-type="funder-name">Narodowe Centrum Nauki</named-content>
<named-content content-type="funderidentifier">10.13039/501100004281</named-content>
</funding-source>
<award-id>/19/B/HS4/</award-id>
<award-id>3</award-id>
</award-group>
</funding-group>
</Export>
XSLT I have tried this xsl but it's not worked properly if i have run this xsl then generate XML single line.
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs"
version="2.0">
<xsl:output method="xml" omit-xml-declaration="no"/>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="//text()">
<xsl:value-of select="translate(.,'
', '')"/>
</xsl:template>
</xsl:stylesheet>

Identify values that dont match in all Nodes and Attributes: XSLT2.0

I need to go over all the xml attributes and text nodes to identify existence of character from list and output the values the characters values that didnt match.
I am able to check the text() nodes but I am not able to perform a check on attributes.
<xsl:template match="#*|node()">
<xsl:variable name="getDelimitersToUseNodes" select="('$' ,'#' ,'*' ,'~')[not(contains(current(),.))]"/>
<xsl:variable name="getDelimitersToUseAttr" select="string-join(('$','#','*','~')[not(contains(#*/,.))],',')"/>
<xsl:variable name="getDelimitersToUse" select="concat(string-join($getDelimitersToUseNodes,','),',',string-join($getDelimitersToUseAttr,','))"/>
<!--xsl:variable name="delim" select="distinct-values($getDelimitersToUse,',')"/-->
<xsl:value-of select="$getDelimitersToUse"/>
</xsl:template>
My mocked up sample file is below
<?xml version="1.0"?>
<sample>
<test1 name="#theGoofy">My$#test</test1>
<test2 value="$##">description test2*</test2>
</sample>
You could process all those text and attribute nodes and make that same check as before. You haven't really said which output format you want, assuming text you could use
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:param name="characters" as="xs:string*" select="'$' ,'#' ,'*' ,'~'"/>
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:template match="/">
<xsl:apply-templates select="//text() | //#*"/>
</xsl:template>
<xsl:template match="text() | #*">
<xsl:value-of select="'Text', ., 'does not contain', $characters[not(contains(current(), .))], '
'"/>
</xsl:template>
</xsl:stylesheet>
to get a result like
Text #theGoofy does not contain $ * ~
Text My$#test does not contain * ~
Text $## does not contain * ~
Text description test2* does not contain $ # ~
If you simply want to check all characters not contained in all text nodes and attribute nodes then an approach like
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:param name="characters" as="xs:string*" select="'$' ,'#' ,'*' ,'~'"/>
<xsl:output method="text"/>
<xsl:strip-space elements="*"/>
<xsl:variable name="nodes-to-inspect" as="node()*" select="//text() | //#*"/>
<xsl:template match="/">
<xsl:value-of select="for $c in $characters return $c[not($nodes-to-inspect[contains(., $c)])]"/>
</xsl:template>
</xsl:stylesheet>
should do.

XSLT: output " without it being parsed

I am trying to achieve the following XML output:
<Foo bar=""" />
My XSLT file is as follows:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="/">
<xsl:variable name="quote">
<xsl:text>"</xsl:text>
</xsl:variable>
<Foo bar="{$quote}"/>
</xsl:template>
</xsl:stylesheet>
Unfortunately, this gives me the output:
<Foo bar="""/>
How do I alter my XSLT to output & quot; without it being parsed into either a " character or a & #34;?
Ian Roberts has already made the very good point that it doesn't actually matter. But if you really, really wanted to do this, then in XSLT 2.0 (but not XSLT 1.0) you could make use of a character map, like so:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" use-character-maps="quotes" />
<xsl:character-map name="quotes">
<xsl:output-character character=""" string="&quot;" />
</xsl:character-map>
<xsl:template match="/">
<xsl:variable name="quote">
<xsl:text>"</xsl:text>
</xsl:variable>
<Foo bar="{$quote}"/>
</xsl:template>
</xsl:stylesheet>

Resources