How do I get text that isn't wrapped in <p> tags to copy using XSLT? - xslt-2.0

I'm running an XSLT script to update questions to a newer format. The authors did not wrap the explanations in <p> tags. When I run the script those explanations drop out. If I wrap them in <p> tags they copy over just fine. I have 1200 questions so I'm really hoping not to have to wrap all the explanations in <p> tags one-by-one.
<!-- attributes, commments, processing instructions, text: copy as is -->
<xsl:template match="#*|comment()|processing-instruction()|/text()">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:if test="*[not(#property)]">
<section property="ktp:explanation-section" typeof="ktp:feedback" data-title="Feedback">
<xsl:attribute name="class">
<xsl:text>ktp-explanation-section</xsl:text>
<!-- append exclusion class, if any -->
<xsl:if test="string-length($exclusions)!=0">
<xsl:value-of select="$exclusions"/>
</xsl:if>
</xsl:attribute>
<xsl:attribute name="data-uuid">
<xsl:call-template name="assignID"/>
</xsl:attribute>
<xsl:apply-templates select="*[not(#property)]|text()"/>
</section>

Related

Need to add 'br' tag after the last <group> element under 'block' element

I want to add 'br' tag after 'group' element under the block element. Basically after the 'group' element in we want break page, that's why we are trying to add break page in output. Below is our input xml structure.
I tried on below XSLT code but unable to get result, please help on this issue:
Input XML:
<?xml version="1.0" encoding="UTF-8"?>
<page>
<stream>
<block>
<group>content here</group>
<group>content here</group>
<group>content here</group>
</block>
</stream>
<stream>
<block>
<group>content here</group>
<group>content here</group>
<group>content here</group>
<!-- please add here br tag -->
</block>
</stream>
</page>
XSLT CODE:
<?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:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="group">
<xsl:element name="p">
<xsl:apply-templates/>
<xsl:if test="position() = last()">
<br></br>
</xsl:if>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?><page>
<stream>
<block>
<p>content here</p>
<p>content here</p>
<p>content here</p>
</block>
</stream>
<stream>
<block>
<p>content here</p>
<p>content here</p>
<p>content here</p>
<!-- please add here br tag -->
</block>
</stream>
</page>
I would match on <xsl:template match="group[last()]"> e.g.
<xsl:template match="group[last()]">
<p>
<xsl:apply-templates/>
</p>
<br/>
</xsl:template>
and for the other groups it seems you want
<xsl:template match="group">
<p>
<xsl:apply-templates/>
</p>
</xsl:template>
It is not clear, however, why your verbal description asks to add a br after the last group of a block while your sample has two blocks and you only add the br in the last block of the last stream. So perhaps you want <xsl:template match="stream[last()]/block/group[last()]"> e.g.
<xsl:template match="stream[last()]/block/group[last()]">
<p>
<xsl:apply-templates/>
</p>
<br/>
</xsl:template>

update more than one result in same uri

I want to update the same result document to accumulate all the meta elements. I have tried to recreate the multiple dita-ot templates to explain the problem here. My question is, is it possible to update keyword.xml in the
<xsl:template match="html" mode="pages">
template itself? maybe using xsl:stream or xsl:accumulator? XSLT 3 and Saxon-HE-9.8.0-12
Input XML
<root>
<article>
<html name="firsthtm">
<head>Head1</head>
<meta>keyword;firsthtm</meta>
</html>
<html name="secondhtm">
<head>Head2</head>
<meta>keyword;secondhtm</meta>
</html>
<html name="thirdhtm">
<head>Head3</head>
<meta>keyword;thirdhtm</meta>
</html>
</article>
XSLT
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="3.0">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="article">
<xsl:apply-templates mode="pages"/>
</xsl:template>
<xsl:template match="html" mode="pages">
<xsl:result-document href="{#name}.html">
<html>
<title>
<xsl:value-of select="#name"/>
</title>
</html>
</xsl:result-document>
<!-- update keyword.xml for each html -->
<xsl:result-document href="keyword.xml">
<root>
<xsl:copy-of select="meta"/>
</root>
</xsl:result-document>
</xsl:template>
firsthtm.htm
<html>
<title>firsthtm</title>
</html>
secondhtm.htm
<html>
<title>secondhtm</title>
</html>
thirdhtm.htm
<html>
<title>thirdhtm</title>
</html>
keyword.xml
<root>
<meta>keyword;secondhtm</meta>
<meta>keyword;secondhtm</meta>
<meta>keyword;thridhtm</meta>
</root>
Just create the result document in the template matching article:
<xsl:template match="article">
<xsl:apply-templates mode="pages"/>
<xsl:result-document href="keyword.xml">
<root>
<xsl:copy-of select="html/meta"/>
</root>
</xsl:result-document>
</xsl:template>
If you want to use the match="html" mode="pages" then you have to decide on which match you want to construct that result e.g on the first
<xsl:template match="html" mode="pages">
<xsl:result-document href="{#name}.html">
<html>
<title>
<xsl:value-of select="#name"/>
</title>
</html>
</xsl:result-document>
<!-- update keyword.xml for first html -->
<xsl:variable name="html-index" as="xs:integer">
<xsl:number/>
</xsl:variable>
<xsl:if test="$html-index = 1">
<xsl:result-document href="keyword.xml">
<root>
<xsl:copy-of select="ancestor::article/html/meta"/>
</root>
</xsl:result-document>
</xsl:if>
</xsl:template>
In simple cases (there are only those html element children for the article and you have used xsl:strip-space) it might suffice to simply test <xsl:if test="position() = 1">.
A simple solution would be moving the xsl:result-document to the article template and copy all html/meta elements from there:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs" version="3.0">
<xsl:template match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="article">
<xsl:apply-templates mode="pages"/>
<xsl:result-document href="keyword.xml">
<root>
<xsl:copy-of select="html/meta"/>
</root>
</xsl:result-document>
</xsl:template>
<xsl:template match="html" mode="pages">
<xsl:result-document href="{#name}.html">
<html>
<title>
<xsl:value-of select="#name"/>
</title>
</html>
</xsl:result-document>
<!-- update keyword.xml for each html -->
</xsl:template>
</xsl:stylesheet>

Create a list of element from nested elements in xslt?

I have a document with nested elements.Now I want to list them one element after another element using XSLT 2.0
Here is the input:
<?xml version="1.0" encoding="UTF-8"?>
<a>
<b>
test text
<b>
this text is in b
</b>
</b>
<b>
this text is
<b>
this text is test
</b>
</b>
</a>
This is what I expect:
<a>
<b>test text</b>
<b>this text is in b</b>
<b>this text is </b>
<b>this text is test</b>
</a>
I have no any idea to do this..I tried grouping concept..but it was not succeeded.Please help me to resolve this.
try this
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="*|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="b[b]">
<xsl:copy>
<xsl:apply-templates select="text()"/>
</xsl:copy>
<xsl:apply-templates select="*"/>
</xsl:template>
<xsl:template match="text()">
<xsl:value-of select="normalize-space(.)"/>
</xsl:template>
</xsl:stylesheet>

match uncaught though declared in XSL

I've the below XML.
<para indent="no">
<star.page>18</star.page> Further to same.
</para>
and when i run the below XSLT.
<xsl:template match="para">
<xsl:value-of select="./node()[1][self::star.page]|./label/node()[1][self::star.page]"/>
<div>
<xsl:choose>
<xsl:when test="./#align">
<xsl:attribute name="class"><xsl:text>para align-</xsl:text><xsl:value-of select="./#align"/></xsl:attribute>
</xsl:when>
<xsl:otherwise>
<xsl:attribute name="class"><xsl:text>para</xsl:text></xsl:attribute>
</xsl:otherwise>
</xsl:choose>
<xsl:apply-templates/>
</div>
</xsl:template>
When i run this, instead of printing <div class="para">18</div>, it is printing <div class="para"></div>
please let me know where am i going wrong and how can i fix this.
Thanks

Getting the value of sibling nodes in XSLT

I have the following XML
<CN>12<CN>
<CT>XYXY</CT>
I need the result AS
<DIV>12 XYXY</DIV>
I'm USING the floowing XSLT but it's not working
<xsl:variable name="x"><xsl:value-of select="CN"/></xsl:variable>
<xsl:template match="CT">
<div class="chap-title"><span><xsl:value-of select="$x"/></span></div>
</xsl:template>
Input:
<input>
<CN>12</CN>
<CT>XYXY</CT>
</input>
XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output indent="yes"
method="xml"
encoding="UTF-8" />
<xsl:template match="/input">
<DIV>
<xsl:value-of select="CN"/>
<xsl:text> </xsl:text>
<xsl:value-of select="CT"/>
</DIV>
</xsl:template>
</xsl:stylesheet>

Resources