Condition getting getting called where it is not supposed to be - regex

I've the below XML.
<?xml version="1.0" encoding="UTF-8"?>
<body>
<para><content-style font-style="bold">18/8/7</content-style> <content-style font-style="italic">(2) Here is the content</content-style>—Contributory negligence accident
<content-style font-style="italic">second v/w datav. </content-style> </para>
</body>
and the below XSL.
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="html" doctype-public="XSLT-compat" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />
<xsl:template match="/">
<hmtl>
<head>
<title>New Version!</title>
</head>
<xsl:apply-templates/>
</hmtl>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="para[node()[position() = 1 and self::content-style[matches(., '(\w+)/(\w+)')]]]">
<div class="para">
<xsl:analyze-string select="." regex="(\w+)/(\w+)/(\w+)">
<xsl:matching-substring>
<a name="{concat('P',regex-group(1),'-',regex-group(2),'-',regex-group(3))}"/>
<span class="phrase">
<xsl:value-of select="."/>
</span>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:analyze-string select="." regex="(\w+)/(\w+)">
<xsl:matching-substring>
<a name="{concat('P',regex-group(1),'-',regex-group(2))}"/>
<span class="phrase">
<xsl:value-of select="."/>
</span>
<xsl:text>     </xsl:text>
</xsl:matching-substring>
<xsl:non-matching-substring>
<xsl:value-of select="."/>
</xsl:non-matching-substring>
</xsl:analyze-string>
</xsl:non-matching-substring>
</xsl:analyze-string>
<xsl:apply-templates select="child::node()[not(self::content-style[1]/text())]"/>
</div>
</xsl:template>
<xsl:template match="content-style">
<xsl:choose>
<xsl:when test="./#format">
<span class="format-{#format}">
<xsl:apply-templates/>
</span>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="fontStyle">
<xsl:value-of select="concat('font-style-',#font-style)"/>
</xsl:variable>
<span class="{$fontStyle}">
<xsl:apply-templates/>
</span>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:transform>
here the problem that i face is the regex is getting called on both content-styles, but i want it to be called only on the content-style where there is no preceding data(text or node), i.e. only on the node like <para><content-style> but not on like <para>(text/node)<content-style>.
Current O/p:
<div class="para"><a name="P18-8-7"></a><span class="phrase">18/8/7</span> (2) Here is the content—Contributory negligence accident
second <a name="Pv-w"></a><span class="phrase">v/w</span> datav. —Contributory negligence accident
</div>
Expected O/P
<div class="para"><a name="P18-8-7"></a><span class="phrase">18/8/7</span> (2) Here is the content—Contributory negligence accident
second <span class="font-style-italic">second v/w datav.</span>
</div>
please let me know where am i going wrong and how can i fix this.
Working Demo
Thanks

Looking at your current XSLT, at the moment when you apply your regex (with analyze-string) you are positioned on a para element, not a content-style, and so doing select="." will get the string value of the entire para element, not just the first node.
What you may need to do is change it to this, so it just does analyse the first content-string (which you know is the first node from the condition in the template match)
<xsl:analyze-string select="content-style[1]" regex="(\w+)/(\w+)/(\w+)">
There is also a problem with this apply-templates in your current template
<xsl:apply-templates select="child::node()[not(self::content-style[1]/text())]"/>
I think what you are trying to do is select the child nodes of para apart from the first child-element. If so, you should change it to this
<xsl:apply-templates select="child::node()[position() > 1]"/>
This may give you what you need.
Alternatively, you could change your current template that matches para to one that matches the first content-style instead:
<xsl:template match="content-style[not(preceding-sibling::node())][matches(., '(\w+)/(\w+)')]">
As this has a condition on it, it will have a higher priority than the template that matches content-style on its own.
As a very simplistic example try this XSLT as a basis
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="content-style[not(preceding-sibling::node())][matches(., '(\w+)/(\w+)')]">
<content-style class="first">
<!-- Regex here! -->
<xsl:apply-templates />
</content-style>
</xsl:template>
<xsl:template match="content-style">
<content-style class="other">
<!-- Other -->
<xsl:apply-templates />
</content-style>
</xsl:template>
</xsl:stylesheet>
Note, you might need to add a strip-space element to your XSLT, otherwise any white space before the first content-style would also count as a proper node.
<xsl:strip-space elements="*" />

Related

XSL - How to ouput nested text-elements at the correct position

I am trying to create an xsl-stylesheet that outputs my xml-contents in the correct order.
Here is an example:
XML:
...<p>This is<mark> a nested <b>text</b></mark></p>...
XSL:
<?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:output method="html" indent="yes"/>
<xsl:template match="/">
<html>
<body>
<h2>
<xsl:value-of select="html/head/title"/>
</h2>
<div style="border:1px solid black;margin:30px;padding:30px;box-sizing:border-box;">
<xsl:for-each select="html/body/div[#class='toc']/table/tr/td/a">
<p><a>
<xsl:attribute name="href" namespace="uri">
<xsl:value-of select="current()/#href"/>
</xsl:attribute>
<xsl:value-of select="current()"/>
</a></p>
</xsl:for-each>
</div>
<xsl:for-each select="html/body/div[#class='chapter']">
<div style="border:1px solid black;margin:30px;padding:30px;box-sizing:border-box;">
<xsl:attribute name="id" namespace="uri"><xsl:value-of select ="current()/#id"/></xsl:attribute>
<p><xsl:value-of select ="current()/#id"/></p>
<xsl:call-template name="rec">
<xsl:with-param name="parents" select="current()"/>
</xsl:call-template>
</div>
</xsl:for-each>
</body>
</html>
</xsl:template>
<xsl:template name="rec">
<xsl:param name="parents"></xsl:param>
<xsl:for-each select="$parents/*">
<xsl:if test="name() = 'img'">
<img class="{#class}" src="{#src}" style="max-width:100%;"/>
</xsl:if>
<xsl:if test="name() != 'img'">
<xsl:element name="{local-name()}">
<xsl:if test="name() != 'figure'">
<xsl:value-of select ="current()"/>
</xsl:if>
<xsl:call-template name="rec">
<xsl:with-param name="parents" select="current()"/>
</xsl:call-template>
</xsl:element>
</xsl:if>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
This outputs:
This is a nested text
a nested text
text
What I am trying to get:
<p>This is<mark> a nested <b>text</b></mark></p>
I have tried just to include a CSS-Stylesheet (which would get rid of this particular problem), however this does not seem to work with images (e.g.), which won´t be displayed but will occure inside most documents.
The XSL-Stylesheet is supposed to be working with multiple documents (I wrote an exporter, that creates xml-files, that roughly follow the same syntax). The important part should only be the recursive function inside <xsl:template name="rec">.
Help would be greatly appreciated. Thanks!
Basic push style, structure and order preserving processing usually relies on the identity transformation template plus custom templates for each node you need to transform e.g.
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="img">
<img class="{#class}" src="{#src}" style="max-width:100%;"/>
</xsl:template>
The duplicated text in your wrong output is created by the repeated use of xsl:value-of in the recursive, named template. If you treat text as nodes and let any copying be handled through adequate templates, like the identity transformation template, you don't output text values several times.

xsl numbering with same elements next to

I need to format some xml data with the following structure
<list>
<item>
Test
</item>
<item>
Testt
</item>
<or-item>
TestOr
</or-item>
<or-item>
TestOrr
</or-item>
<item>
Testtt
</item>
<or-item>
TestOrrr
</or-item>
<item>
Testttt
</item>
</list>
with xsl:number the or-item must be formatted with the second level count on that position. I know it would be better to structure the or-item inside that item but the data is given like that.
I need a way to count the or-item next to the current or-item to calculate the numbering for xsl:number
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" version="1.1"
xmlns:axf="http://www.antennahouse.com/names/XSL/Extensions" xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output encoding="UTF-8" method="html" indent="yes"/>
<xsl:template match="list">
<div>
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="item">
<div>
<xsl:number count="item"/>
<xsl:value-of select="."/>
</div>
</xsl:template>
<xsl:template match="or-item">
<div style="padding-left: 10px">
<xsl:number value="count(//or-item)" format="a) "/>
<xsl:value-of select="."/>
</div>
</xsl:template>
</xsl:stylesheet>
Edit
I am using XSLT 1.1 with xsltproc on linux but 2.0 whould be possible if neccessary
As the target format is HTML, it seems you could rely on creating the appropriate nested HTML ordered lists by using xsl:for-each-group and group-starting-with="item":
<xsl:template match="list">
<ol>
<xsl:for-each-group select="*" group-starting-with="item">
<li>
<xsl:value-of select="."/>
<xsl:where-populated>
<ol>
<xsl:apply-templates select="tail(current-group())"/>
</ol>
</xsl:where-populated>
</li>
</xsl:for-each-group>
</ol>
</xsl:template>
<xsl:template match="or-item">
<li>
<xsl:value-of select="."/>
</li>
</xsl:template>
https://xsltfiddle.liberty-development.net/ejivJrM
That example uses some XSLT/XPath 3 stuff like were-populated and tail but in case that XSLT 2 compatility is needed then it could be replaced by <xsl:if test="subsequence(current-group(), 2)"><ol><xsl:apply-templates select="subsequence(current-group(), 2)"/></xsl:if>.
And of course the use of HTML ordered lists is not necessary, if needed/wanted you could just transform the input to nested divs with the used grouping approach and then in a second step use format-number as you seem to want to do:
<xsl:template match="list">
<xsl:variable name="nested-list">
<xsl:for-each-group select="*" group-starting-with="item">
<xsl:copy>
<xsl:value-of select="."/>
<xsl:copy-of select="tail(current-group())"/>
</xsl:copy>
</xsl:for-each-group>
</xsl:variable>
<div>
<xsl:apply-templates select="$nested-list"/>
</div>
</xsl:template>
<xsl:template match="item">
<div>
<xsl:number/>
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="or-item">
<div style="padding-left: 10px">
<xsl:number format="a) "/>
<xsl:value-of select="."/>
</div>
</xsl:template>
https://xsltfiddle.liberty-development.net/ejivJrM/1
You can produce the expected output by simply adjusting the xsl:number instruction:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" encoding="utf-8"/>
<xsl:template match="/list">
<div>
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="item">
<div>
<xsl:number/>
<xsl:value-of select="."/>
</div>
</xsl:template>
<xsl:template match="or-item">
<div style="padding-left: 10px">
<xsl:number level="any" from="item" format="a) "/>
<xsl:value-of select="."/>
</div>
</xsl:template>
</xsl:stylesheet>

Flattening with XSLT: I want to move one kind element one level

I have a XML file where elements B are inside elements A and I want to move them up. From:
<?xml version="1.0" encoding="utf-8"?>
<root>
<A>
<C>Text</C>
Text again
More text
<D>Other text</D>
<B>Text again</B>
<C>No</C>
<D>May be</D>
<B>What?</B>
</A>
<A>
Something
<B>Nothing</B>
<D>Again</D>
<B>Content</B>
End
</A>
</root>
I would like to have:
<?xml version="1.0" encoding="utf-8"?>
<root>
<A>
<C>Text</C>
Text again
More text
<D>Other text</D>
</A>
<B>Text again</B>
<A>
<C>No</C>
<D>May be</D>
</A>
<B>What?</B>
<A>
Something
</A>
<B>Nothing</B>
<A>
<D>Again</D>
</A>
<B>Content</B>
<A>
End
</A>
</root>
The closest XSLT program I have is this:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="#* | node()">
<xsl:copy>
<xsl:apply-templates select="#* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="A">
<xsl:for-each select="*">
<xsl:choose>
<xsl:when test="name()='B'">
<xsl:apply-templates select="."/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="A">
<xsl:apply-templates select="."/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
It has two problems: it ignores text nodes (this is probably just a matter of adding |text() to the select="*") but, more important, it creates a element for each node while I would like them to stay together under one . For instance, the above stylesheet makes:
<A><C>No</C></A>
<A><D>May be</D></A>
where I want:
<A><C>No</C>
<D>May be</D></A>
In my XML files, are always direct children of , and there is no or nesting.
The main use case is producing HTML where UL and OL cannot be inside a P.
This question is related but not identical to xslt flattening out child elements in a DocBook para element (and may be also to Flatten xml hierarchy using XSLT
)
As I said in the comment to your question, this is not about moving elements up in hierarchy. It is about grouping nodes, and creating a new parent A element for each group determined by the dividing B element.
In XSLT 1.0 this can be achieved using a so-called sibling recursion:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/root">
<xsl:copy>
<xsl:apply-templates select="A"/>
</xsl:copy>
</xsl:template>
<xsl:template match="A">
<xsl:copy>
<xsl:apply-templates select="node()[1][not(self::B)]" mode="sibling"/>
</xsl:copy>
<xsl:apply-templates select="B[1]" mode="sibling"/>
</xsl:template>
<xsl:template match="node()" mode="sibling">
<xsl:copy-of select="." />
<xsl:apply-templates select="following-sibling::node()[1][not(self::B)]" mode="sibling"/>
</xsl:template>
<xsl:template match="B" mode="sibling">
<xsl:copy-of select="." />
<xsl:if test="following-sibling::node()[normalize-space()]">
<A>
<xsl:apply-templates select="following-sibling::node()[1][not(self::B)]" mode="sibling"/>
</A>
<xsl:apply-templates select="following-sibling::B[1]" mode="sibling"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
An XSLT-1.0 solution - which is quite ugly - is the following. The output is as desired, but only for this simple MCVE. A general solution would be far more complicated as #michael.hor257k mentioned in the comments. Without more data it is unlikely to create a better solution in XSLT-1.0. Solutions for XSLT-2.0 and above may simplify this.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/root">
<xsl:copy>
<xsl:for-each select="A">
<xsl:if test="normalize-space(text()[1])">
<A>
<xsl:copy-of select="text()[1]" />
</A>
</xsl:if>
<xsl:if test="preceding::*">
<xsl:copy-of select="B[1]" />
</xsl:if>
<A>
<xsl:copy-of select="C[1] | C[1]/following-sibling::text()[1] | D[1]" />
</A>
<xsl:if test="not(preceding::*)">
<xsl:copy-of select="B[1]" />
</xsl:if>
<A>
<xsl:copy-of select="C[2] | C[2]/following-sibling::text()[1]" />
<xsl:if test="D[2]">
<xsl:copy-of select="D[2]" />
</xsl:if>
</A>
<xsl:copy-of select="B[2]" />
<xsl:if test="normalize-space(text()[last()])">
<A>
<xsl:copy-of select="text()[last()]" />
</A>
</xsl:if>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Concerning the situation of
<A><C>No</C></A>
<A><D>May be</D></A>
It is handled appropriately in the above code. So its output is
<A>
<C>No</C>
<D>May be</D>
</A>
Easy in XSLT 2 or 3 with group-adjacent=". instance of element(B)" or group-adjacent="boolean(self::B)", here is an XSLT 3 example (XSLT 3 is supported by Saxon 9.8 or 9.9 on Java and .NET (https://sourceforge.net/projects/saxon/files/Saxon-HE/) and by Altova since 2017 releases):
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="#all"
version="3.0">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="A">
<xsl:for-each-group select="node()" group-adjacent=". instance of element(B)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy select="..">
<xsl:apply-templates select="current-group()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
https://xsltfiddle.liberty-development.net/gWmuiKv
In XSLT 2 you need to spell out the <xsl:mode on-no-match="shallow-copy"/> as the identity transformation template and use xsl:element instead xsl:copy:
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="A">
<xsl:for-each-group select="node()" group-adjacent=". instance of element(B)">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<xsl:apply-templates select="current-group()"/>
</xsl:when>
<xsl:otherwise>
<xsl:element name="{name(..)}" namespace="{namespace-uri(..)}">
<xsl:apply-templates select="current-group()"/>
</xsl:element>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:template>
</xsl:transform>
http://xsltransform.hikmatu.com/pPqsHT2

How do I build an id and count at the same time?

In the following code, I need, in the place of the two xxxx's, to have the name of the element (name()), so h1, h2 or h3, whatever the match may be. So the second xxxx must be the count of the h1/h2/h3 in that file. The attribute will then look like "h1_4", or h3_15" etc.
How do I do that ?
<xsl:template match="h1[not(#id)] | h2[not(#id)] | h3[not(#id)]" >
<xsl:element name="{name()}" >
<xsl:attribute name="id">xxxx_<xsl:value-of><xsl:number count="xxxx" /></xsl:value-of></xsl:attribute>
</xsl:element>
<xsl:apply-templates/>
</xsl:template>
As I said, the request is ambiguous. The following stylesheet:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- identity transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="h1[not(#id)] | h2[not(#id)] | h3[not(#id)]" >
<xsl:variable name="name" select="name()" />
<xsl:copy>
<xsl:attribute name="id">
<xsl:value-of select="$name"/>
<xsl:text>_</xsl:text>
<xsl:value-of select="count(preceding::*[name()=$name]) + 1"/>
</xsl:attribute>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
when applied to the following test input:
<root>
<h1 id="h1_1"/>
<h2 type="abc"/>
<h3 type="xyz"/>
<h1>content</h1>
<h3 id="h3_2" type="efg"/>
<h2/>
</root>
will produce:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<h1 id="h1_1"/>
<h2 id="h2_1" type="abc"/>
<h3 id="h3_1" type="xyz"/>
<h1 id="h1_2">content</h1>
<h3 id="h3_2" type="efg"/>
<h2 id="h2_2"/>
</root>
You're on the right track using xsl:number, how about:
<xsl:template match="h1 | h2 | h3" >
<xsl:copy>
<xsl:attribute name="id">
<xsl:value-of select="name()"/>
<xsl:text>_</xsl:text>
<xsl:number level="any" />
</xsl:attribute>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
I'm assuming an identity template to copy the rest of the document as-is, and that being the case I've simplified the match pattern - you don't need to check for not(#id) as where there is an id attribute in the input it will overwrite the one being created by the xsl:attribute.

How to parse nested tags using XSLT in sequence?

I have below scenario for my XML.
<content>
<para>text-1 <emphasis type="bold">text-2</emphasis> text-3</para>
</content>
I want to parse it like below
<content>
<p>text-1 <b>text-2</b> text-3</p>
</content>
I have created my XSLT as below
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output method="xml" encoding="ISO-8859-1" indent="no"/>
<xsl:template name="para">
<p>
<xsl:value-of select="text()" disable-output-escaping="yes"/>
<xsl:for-each select="child::*">
<xsl:if test="name()='emphasis'">
<xsl:call-template name="emphasis"/>
</xsl:if>
</xsl:for-each>
</p>
</xsl:template>
<xsl:template name="emphasis">
<xsl:if test="attribute::type = 'bold'">
<b>
<xsl:value-of select="text()" disable-output-escaping="yes"/>
</b>
</xsl:if>
</xsl:template>
<xsl:template match="/">
<content>
<xsl:for-each select="content/child::*">
<xsl:if test="name()='para'">
<xsl:call-template name="para"/>
</xsl:if>
</xsl:for-each>
</content>
</xsl:template>
</xsl:stylesheet>
XSLT provided above is generating output like below
<content>
<p>text-1 text-3<b>text-2 </b></p>
</content>
Please guide me with your suggestions, how can I get my desire output?
To do this, you just need to extend the standard Identity Transform with special cases for matching your para and emphasis elements. For example, for para elements you would the following to replace para with p and then continue matching all the child nodes
<xsl:template match="para">
<p>
<xsl:apply-templates select="#*|node()"/>
</p>
</xsl:template>
So, given the following XSLT
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" />
<!-- This is the Identity Transform -->
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Replace para with p -->
<xsl:template match="para">
<p>
<xsl:apply-templates select="#*|node()"/>
</p>
</xsl:template>
<!-- Replace emphasis with b -->
<xsl:template match="emphasis[#type='bold']">
<b>
<xsl:apply-templates select="node()"/>
</b>
</xsl:template>
</xsl:stylesheet>
When applied to the following input XML
<content>
<para>text-1 <emphasis type="bold">text-2</emphasis> text-3</para>
</content>
The following is output
<content>
<p>text-1 <b>text-2</b> text-3</p>
</content>
You should be able to see how easy it is to extend to other cases should you input XML have more tags to transform.
do it like this ;)
<?xml version="1.0" encoding="utf-8" ?>
<xsl:stylesheet
version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>
<xsl:template match="content">
<content><xsl:apply-templates select="para" /></content>
</xsl:template>
<xsl:template match="emphasis [#type='bold']">
<b><xsl:value-of select="." /></b>
</xsl:template>
</xsl:stylesheet>
when you do it like this the default template will catch text-1 and text-3