what does 'pop' means in a xslt example on w3.org - xslt-2.0

the code is a example in second from last:"Example: Output Hierarchic Section Numbers",
https://www.w3.org/TR/2017/REC-xslt-30-20170608/#accumulator-examples
<xsl:accumulator name="section-nr" as="xs:integer*"
initial-value="0">
<xsl:accumulator-rule match="section" phase="start"
select="0, head($value)+1, tail($value)"/>
<xsl:accumulator-rule match="section" phase="end"
select="tail($value) (:pop:)"/>
</xsl:accumulator>
<xsl:template match="section">
<p>
<xsl:value-of select="reverse(tail(accumulator-before('section-nr')))"
separator="."/>
</p>
<xsl:apply-templates/>
</xsl:template>
What does the word ":pop:" in the second "xsl:accumulator-rule" means, Is it a key word or something defined ? thanks

That is an XPath comment which is a string that is delimited by the symbols (: and :)
Have a look at "5.5.2 Syntax of Patterns" of the link you provided:
https://www.w3.org/TR/2017/REC-xslt-30-20170608/#pattern-syntax

Related

Simple XSLT Transformation When XML elements have text nodes and child nodes

I am new to xslt and am trying to transform the following xml:
<li>Hi there <person>David</person> , how is it going? </li>
I would like to transform this to another xml to something like:
<response>Hi there PERSON_NAME , how is it going? </response>
What I have so far is this:
<xsl:template match="li">
<response><xsl:value-of select="text()"/>
<xsl:choose>
<xsl:when test="person">
<xsl:text> PERSON_NAME </xsl:text>
</xsl:when>
</xsl:choose>
</response>
</xsl:template>
This is the output I get:
<response>Hi there , how is it going? PERSON_NAME</response>
Not exactly what I wanted. I am new to xslt and read a book. I did not find any example where there was a situation where an xml element had a child node in between its text value. Not sure if xslt can handle this or I am missing something fundamental. Any help would be greatly appreciated. I am using xslt 2.0
You can simply define two template to handle your condition.
<xsl:template match="li">
<response>
<xsl:apply-templates/>
</response>
</xsl:template>
<xsl:template match="person">
<xsl:text>PERSON_NAME</xsl:text>
</xsl:template>

pattern not matching though declared

I've the below XML.
<root>
<para>
<label>5.</label> In essence, the Court in <star.page>19</star.page>
</para>
<para>
<label><star.page>21</star.page> 13.</label> Frankly, I cannot see how
one can escape
</para>
</root>
and using the below XSLT.
<xsl:template match="para">
<xsl:apply-templates select="./node()[1][self::star.page]|./label/node()[1][self::star.page]" mode="first"/>
</xsl:template>
<xsl:template match="star.page" mode="first">
<xsl:if test="preceding::star.page">
<xsl:processing-instruction name="pb">
<xsl:text>label='</xsl:text>
<xsl:value-of select="."/>
<xsl:text>'</xsl:text>
<xsl:text>?</xsl:text>
</xsl:processing-instruction>
<a name="{concat('pg_',.)}"/>
</xsl:if>
</xsl:template>
here when i try to run this code, the first para star.page is getting caught, but the second star.page, i.e. <para><label><star.page>21</star.page> 13.</label>... is not getting caught. please let me know where am i going wrong. here i'm taking [1], since i want to catch the first occurance.
Thanks
I just tried your code on xmlplayground, both the star.page elements reach the template but the if clause is preventing the first from reaching the output.

XSLT: How to access elements of type both namespace and without namespaces within same article

Please suggest to access the elements which are not having any namespaces. However my code able to access and alter the nodes (elements) which are having namespaces. I am using XSLT2 version. Find my xml (I used DTD path mapped to my local path, please suggest also for access the XML without DTD help.
InPut XML:
<!DOCTYPE article PUBLIC "-//ES//DTD journal article DTD version 5.2.0//EN//XML" "D:/DTDs/Els-parser/art520.dtd">
<article>
<fm>
<ce:title>The title</ce:title>
<ce:author-group>
<ce:author><ce:surname>Rudramuni</ce:surname><ce:given-names>TP</ce:given-names></ce:author>
</ce:author-group>
</fm>
<body>
<ce:sections>
<ce:section>
<ce:section-title>The first Head</ce:section-title>
<ce:para>Tha first para</ce:para>
</ce:section>
</ce:sections>
</body>
<back>
<ref><ce:author>Vijay</ce:author></ref>
</back>
</article>
XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ce="http://www.elsevier.com/xml/common/dtd"
xmlns:sb="http://www.elsevier.com/xml/common/struct-bib/dtd"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:mml="http://www.w3.org/1998/Math/MathML"
version='2.0'>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="fm">
<xsl:element name="ce:front"><xsl:apply-templates/></xsl:element>
</xsl:template>
<xsl:template match="ce:author">
<xsl:element name="name"><xsl:apply-templates/></xsl:element>
</xsl:template>
</xsl:stylesheet>
Required Result:
<?xml version="1.0" encoding="UTF-8"?>
<article>
<ce:front>
<ce:title>The title</ce:title>
<ce:author-group><name><ce:surname>Rudramuni</ce:surname><ce:given-names>TP</ce:given-names></name></ce:author-group>
</ce:front>
<body><ce:sections><ce:section><ce:section-title>The first Head</ce:section-title><ce:para>Tha first para</ce:para></ce:section></ce:sections></body>
<back>
<ref><name>Vijay</name></ref>
</back>
</article>
But I am getting some extra namespaces like "xmlns="http://www.elsevier.com/xml/ja/dtd" and xmlns="", and some extra attributes are found for some elements like view="all". Thanks in advance. Please suggest.
You seem to ask a lot of questions on XSLT 2.0 recently, which is ok of course, but please kindly consider these guidelines when asking questions:
Use valid examples that we can reproduce your problem with. Your examples, in this and other questions, are not well-formed (missing namespaces in this question for instance), which makes it hard to help you (and they will downvote or close your question, see How to ask).
Tone down the examples to the bare minimum, otherwise people will not run to help you as it is too hard to understand the question asked. In this case, a two-line XML and XSLT would explain your issue.
Run the code you paste here and copy the output (or errors) you get. In this question for instance, the output is not namespace-well-formed, which cannot possibly be the output of any XSLT processor.
To answer your question, you can use a wild-card NameTest, which selects that name in any namespace:
select="*:something"
select="*:foo/*:bar"
select="*:foo[contains(., #*:some-attr)]"

Can I apply a character map to a given node?

If I look at the xslt specs it seems a character map applies to the whole document, bit is it also possible to use it on a given node, or within a template ?
Example : I have a node containing look up values, but they might contain characters that don't play well with regular expressions when using it in another template. For now I use a replace functionwhich works well,, but after a few characters that becomes pretty hard to read or maintain. So if I have something like this :
<xsl:variable name="myLookup" select="
replace(
replace(
replace(
replace(
string-join(/*/lookup/*, '|'),
'\[','\\['),
'\]','\\]'),
'\(','\\('),
'\)','\\)')
"/>
is there a way to achieve something like below fictitious example ?
<xsl:character-map name="escapechar">
<xsl:output-character character="[" string="\[" />
<xsl:output-character character="]" string="\]" />
<xsl:output-character character="(" string="\(" />
<xsl:output-character character=")" string="\)" />
</xsl:character-map>
<xsl:variable name="myLookup" select="string-join(/*/lookup/*, '|')" use-character-map="escapechar"/>
I know this is not working at all, it is just to make my request a bit visual.
Any idea ?
I think character maps in XSLT 2.0 are a serialization feature to be applied when a result tree is serialized to a file or stream so I don't see how you could apply one to a certain string or certain node during a transformation.
As for escaping meta characters of regular expression patterns, maybe http://www.xsltfunctions.com/xsl/functx_escape-for-regex.html helps.
Character maps is only a serialization feature, which means that it is only executed when the final output of a transformation is produced. However, you can significantly simplify your current code.
Just use:
replace($pStr, '(\[|\]|\(|\))','\\$1')
Here is a complete example:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:my="my:my">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/*">
<xsl:value-of select="my:escape(.)"/>
</xsl:template>
<xsl:function name="my:escape" as="xs:string">
<xsl:param name="pStr" as="xs:string"/>
<xsl:value-of select="replace($pStr, '(\[|\]|\(|\))','\\$1')"/>
</xsl:function>
</xsl:stylesheet>
When this transformation is applied on the following XML document:
<t>([a-z]*)</t>
the wanted, correct result is produced:
\(\[a-z\]*\)

XPath syntax error thrown when using evaluate() method

Still i am getting the below error
Error at xsl:param on line 6 of file:/E:/saxon/parastyleText.xsl:
XPST0003: XPath syntax error at char 0 on line 6 in {...le/#w:val[matches(., c
oncat...}:
Invalid character '^' in expression
Failed to compile stylesheet. 1 error detected.
Modified XSL:
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" 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">
<xsl:param name="styleName" select="'articletitle'"/>
<xsl:param name="tagName" select="'//w:p[w:pPr/w:pStyle/#w:val[matches(., concat('^(',$styleName,')$'),'i')]]'"/>
<xsl:output method="text"/>
<xsl:template match="/">
<xsl:value-of select="saxon:evaluate($tagName)" xmlns:saxon="http://saxon.sf.net/"/><xsl:text>
</xsl:text>
</xsl:template>
</xsl:stylesheet>
Please dont reply that, quotes will make 'tagName' as string and remove those quotes. This value will be actually passed from java as a string , tats y for testing purpose i have passed this xpath as string.
According to the online documentation http://www.saxonica.com/documentation9.1/extensions/functions.html Saxon 9.1 supports an evaluate function in the Saxon namespace http://saxon.sf.net/. So with Saxon 9.1 try <xsl:value-of select="saxon:evaluate($tagName)" xmlns:saxon="http://saxon.sf.net/"/>. Of course you can move the namespace declaration up to the xsl:stylesheet element if you want, I just put it on the xsl:value-of in this post for a short but complete sample of code.
Also note that with your variable named tagName it is likely that you simply have a single element name, in that case it might suffice to use <xsl:value-of select="*[local-name() eq $tagName]"/>.

Resources