Apply templates not working as desired - xslt

Given the following xml inputs:
file1:
<?xml version="1.0" encoding="UTF-8"?>
<File1 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<code code="file1_code" displayName="file1_display" codeSystem="file1_cs" codeSystemName="file1_csn"/>
<title>Title of file1</title>
<component typeCode="COMP">
<structuredBody classCode="DOCBODY">
<component typeCode="COMP">
<section>
<templateId root="someRoot_file1" assigningAuthorityName="someAuhthority_file1"/>
<code code="file1-sec1_code" displayName="file1_sec1_display" codeSystem="file1_sec1_cs" codeSystemName="file1_sec1_csn"/>
<title>Tile of sec 1 from file1</title>
<text>
<content styleCode="Italics">
Text of sec 1 from file1
</content>
</text>
<entry> file 1 sec 1
</entry>
</section>
</component>
<component typeCode="COMP">
<section classCode="DOCSECT">
<code code="file1_sec2_code" codeSystem="file2_sec2_cs" displayName="file2_sec2_display" codeSystemName="file2_sec2_csn"/>
<title>Tile from sec 2 file 1</title>
<text>
<content styleCode="Italics">
Text from file1 sec 2
</content>
</text>
<entry typeCode="test"> file2 sec 2
</entry>
</section>
</component>
</structuredBody>
</component>
</File1>
file2:
<?xml version="1.0"?>
<A>
<title value="Title of file2"/>
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<p>File 2 Text</p>
</div>
</text>
<section>
<code>
<coding>
<system value="sec 1 file2 sys"/>
<code value="sec 1 file 2 code"/>
<display value="sec 1 file 2 display"/>
</coding>
</code>
<title>Title of sec 1 file2</title>
<text>
<content styleCode="Italics">Section 1 Text
</content>
</text>
<entry>
<someEntry>
</someEntry>
</entry>
</section>
<section>
<code>
<coding>
<system value="sec 2 file2 sys"/>
<code value="sec 2 file 2 code"/>
<display value="sec 2 file 2 display"/>
</coding>
</code>
<title>Title of sec 2 file2</title>
<text>
<content styleCode="Italics">Section 2 file2 Text
</content>
</text>
<entry>
<someEntry> entry sec 2 file 2
</someEntry>
</entry>
</section>
</A>
and the following xslt:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*" />
<xsl:variable name="input" select="/" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<Bundle>
<id value="test"/>
<type value="document"/>
<entry>
<resource>
<xsl:apply-templates select="document('file2.xml')/*"/>
</resource>
</entry>
</Bundle>
</xsl:template>
<xsl:template match="text">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<p>This is the text from the stylesheet </p>
</div>
</text>
</xsl:template>
<xsl:template match="title">
<xsl:apply-templates select="$input/File1/title"/>
</xsl:template>
<xsl:template match="section[1]">
<xsl:apply-templates select="$input/File1/component/structuredBody/component/section"/>
</xsl:template>
<xsl:template match="section[2]"/>
<xsl:template match="File1/title">
<title>
<xsl:attribute name="value">
<xsl:value-of select="." />
</xsl:attribute>
</title>
</xsl:template>
<xsl:template match = "File1/component/structuredBody/component/section">
<section>
<xsl:apply-templates/>
</section>
</xsl:template>
</xsl:stylesheet>
And this is the output:
<?xml version="1.0" encoding="UTF-8"?>
<Bundle>
<id value="test"/>
<type value="document"/>
<entry>
<resource>
<A>
<title value="Title of file1"/>
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<p>This is the text from the stylesheet </p>
</div>
</text>
<section>
<templateId xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" root="someRoot_file1" assigningAuthorityName="someAuhthority_file1"/>
<code xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" code="file1-sec1_code" displayName="file1_sec1_display" codeSystem="file1_sec1_cs" codeSystemName="file1_sec1_csn"/>
<title value="Title of file1"/>
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<p>This is the text from the stylesheet </p>
</div>
</text>
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</section>
<section>
<code xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" code="file1_sec2_code" codeSystem="file2_sec2_cs" displayName="file2_sec2_display" codeSystemName="file2_sec2_csn"/>
<title value="Title of file1"/>
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<p>This is the text from the stylesheet </p>
</div>
</text>
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" typeCode="test"/>
</section>
</A>
</resource>
</entry>
</Bundle>
And this is the expected output:
<?xml version="1.0" encoding="UTF-8"?>
<Bundle>
<id value="test"/>
<type value="document"/>
<entry>
<resource>
<A>
<title value="Title of file1"/>
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<p>This is the text from the stylesheet </p>
</div>
</text>
<section>
<templateId xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" root="someRoot_file1" assigningAuthorityName="someAuhthority_file1"/>
<code xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" code="file1-sec1_code" displayName="file1_sec1_display" codeSystem="file1_sec1_cs" codeSystemName="file1_sec1_csn"/>
<title>Tile of sec 1 from file1</title>
<text>
<content styleCode="Italics">
Text of sec 1 from file1
</content>
</text>
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</section>
<section>
<code xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" code="file1_sec2_code" codeSystem="file2_sec2_cs" displayName="file2_sec2_display" codeSystemName="file2_sec2_csn"/>
<title>Tile from sec 2 file 1</title>
<text>
<content styleCode="Italics">
Text from file1 sec 2
</content>
</text>
<entry xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" typeCode="test"/>
</section>
</A>
</resource>
</entry>
</Bundle>
I have the following questions:
Why is the title in the section elements coming from the main title (i.e. File1/title) when the apply templates is within File1/component/structuredBody/component/section? I was expecting that the title of the section will be output, which is what is desired. Even more confusing is that it does indeed output the elements in the section like code, entry and so on but title and text (see q2 below) seems to be treated differently and I can't for the life of me understand why.
Same with text. Why is the text for section not being output?
Here is my presumably false understanding of the process:
We start with the <xsl:template match="/"> and create elements Bundle, id etc. and then using <xsl:apply-templates select="document('file2.xml')/*"/> we match the top element of file2 (A) and since we don't have a template matching it explicitly, the identity template is called, copies it and process its child elements, which are text, title and section. For each of these child elements, it looks for a matching template. it finds them and matches them.
For element section however, it matches only the first section element because of <xsl:template match="section[1]"> and then because of <xsl:apply-templates select="$input/File1/component/structuredBody/component/section"/> in the template, it looks for a template matching children of section in FIle1, which are code, text, title and templateId. It finds no such explicitly defined template, so calls the identity templates for them, copies and processes them till the end. At least that is my understanding of it.

Why is the title in the section elements coming from the main title
Because any time the processor is instructed to apply templates to a title, it looks for the best-matching template to apply, and finds this:
<xsl:template match="title">
<xsl:apply-templates select="$input/File1/title"/>
</xsl:template>
This changes the context to the title in File1.xml, and the best-matching template for this one is:
<xsl:template match="File1/title">
<title>
<xsl:attribute name="value">
<xsl:value-of select="." />
</xsl:attribute>
</title>
</xsl:template>
and that is the result you see.
Same with text. Why is the text for section not being output?
-- edited in response to the following clarification: --
When I say text I am talking about text elements only.
The original text element (child of section in File1.xml) is not being output because you have a specific template matching it and outputting something else instead:
<xsl:template match="text">
<text>
<status value="generated"/>
<div xmlns="http://www.w3.org/1999/xhtml">
<p>This is the text from the stylesheet </p>
</div>
</text>
</xsl:template>

# michael.hor257k and #Michael Kay yeah, that was definitely the case, that I misunderstood how xsl:apply-templates works with regards to context . I thought because I called the xsl:apply-templates from within xsl:template match = "$input/File1/component/structuredBody/component/section"> that it will only look for match templates that match the children of section. In other words, I thought it will look for templates like “<xsl:template match=”File1/component/structuredBody/component/section/title"> but that is clearly not the case.
xsl:apply-templates simply looks for the children and then looks for a match template regardless of the context from which they were called. So, it will look for title or text template that matches and if it finds them, it will match them.
The easiest solution I could find that seems to solve the problem is to add a path to the title and text templates. In other words, instead of just <xsl:template match="text"> I should have <xsl:template match="A/text">. Same for title. This way, the xsl:apply-templates will not apply <xsl:template match="A/text"> as the title in section is not a child of A. So given that no matching explicit template is defined, the identity template will be applied and will output the title of section as desired.

Related

inside title roman numbers as attribute values

I want to add the tag inside value as num value and removing the section roman numbers and symbol inside the title tag
My Input XML File:
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="d102e3" xml:lang="en-US">
<title outputclass="Chapter_Title">Base Food</title>
<subsection id="d102e11" xml:lang="en-US" outputclass="Heading_1">
<title> § I Nothing</title>
<body>
<p outputclass="Body_Text">1Y The Act also states that the may undertake a review of the definition of the term.</p>
</body>
</subsection>
<subsection id="d102e20" xml:lang="en-US" outputclass="Heading_2">
<title> § II Proposed Amendments: “Accredited Natural Person”</title>
<body>
</subsection>
<p outputclass="Body_Text">1Y The Act also states that the may undertake a review of the definition of the term.</p>
</body>
</chapter>
My XSLT Coding is
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes" omit-xml-declaration="no"></xsl:output>
<xsl:template match="/">
<xsl:apply-templates></xsl:apply-templates>
</xsl:template>
<xsl:template match="*[contains(#class,' chapter/chapter ')]">
<chapter>
<xsl:apply-templates/>
</chapter>
</xsl:template>
<xsl:template match="subsection">
<section level="sect{format-number(count(preceding::subsection)+1,'0000')}" num="I" number-type="manual">
<xsl:apply-templates/>
</section>
</xsl:template>
<xsl:template match="*[contains(#class,' topic/p ')]">
<para>
<xsl:apply-templates/>
</para>
</xsl:template>
<xsl:template match="*[contains(#class,' topic/title ')]">
<title>
<xsl:apply-templates/>
</title>
</xsl:template>
</xsl:stylesheet>
</xsl:stylesheet>
I am getting output as
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<chapter>
<title>Base Food</title>
<section level="sect0001" num="I" number-type="manual">
<title> § I Nothing</title>
<para>1Y The Act also states that the may undertake a review of the definition of the term.</para>
</section>
<section level="sect0001" num="I" number-type="manual">
<title> § II Proposed Amendments: “Accredited Natural Person”</title>
<para>1Y The Act also states that the may undertake a review of the definition of the term.</para>
</section>
</chapter>
but i want output in side title tag roman number format in 'num' attributes and remove the number and symbol '§ I' inside title tag:
output needed as
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<chapter>
<title>Base Food</title>
<section level="sect1" num="§ I" number-type="manual">
<title>Nothing</title>
<para>1Y The Act also states that the may undertake a review of the definition of the term.</para>
</section>
<section level="sect2" num="§ II" number-type="manual">
<title>Proposed Amendments: “Accredited Natural Person”</title>
<para>1Y The Act also states that the may undertake a review of the definition of the term.</para>
</section>
</chapter>
Please assist me.
Thanks in Advance

XSLT: Using xsl:key in nested XML structures

EXAMPLE
Here is an example from MSDN. It show how to transform a XML file into HTML using xsl:key.
Example XML (input)
<books>
<book title="XML Today" author="David Perry" release="2016"/>
<book title="XML and Microsoft" author="David Perry" release="2015"/>
<book title="XML Productivity" author="Jim Kim" release="2015"/>
</books>
Example XSL (input)
<xsl:key name="title-search" match="book" use="#author"/>
<xsl:template match="/">
<HTML>
<BODY>
<xsl:for-each select="key('title-search', 'David Perry')">
<DIV>
<xsl:value-of select="#title"/>
</DIV>
</xsl:for-each>
</BODY>
</HTML>
</xsl:template>
Example HTML (output)
<HTML>
<BODY>
<DIV>XML Today</DIV>
<DIV>XML and Microsoft</DIV>
</BODY>
</HTML>
MY PROBLEM
I would like to produce the same HTML output but using a different XML input. How should the corresponding XSL file look like?
My XML (input)
<books>
<book>
<a n="author"><s>David Perry</s></a>
<a n="title"><s>XML Today</s></a>
<a n="release"><i>2016</i></a>
</book>
<book>
<a n="author"><s>David Perry</s></a>
<a n="title"><s>XML and Microsoft</s></a>
<a n="release"><i>2015</i></a>
</book>
<book>
<a n="author"><s>Jim Kim</s></a>
<a n="title"><s>XML Productivity</s></a>
<a n="release"><i>2015</i></a>
</book>
</books>
My XSL (input)
???
My HTML (output)
<HTML>
<BODY>
<DIV>XML Today</DIV>
<DIV>XML and Microsoft</DIV>
</BODY>
</HTML>
In the first example, your key matched book elements by their author attribute, but in the new XML, you want to match them by the a element where the n attribute is "author", so the key looks like this.
<xsl:key name="title-search" match="book" use="a[#n='author']/s"/>
Then, to get the title for the a matched book you would do this...
<xsl:value-of select="a[#n='title']/s"/>
Therefore your XSLT would look like this:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" />
<xsl:key name="title-search" match="book" use="a[#n='author']/s"/>
<xsl:template match="/">
<HTML>
<BODY>
<xsl:for-each select="key('title-search', 'David Perry')">
<DIV>
<xsl:value-of select="a[#n='title']/s"/>
</DIV>
</xsl:for-each>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
You could actually drop the /s in the expressions here, if the s element was only ever going to be the only element under each a element.
This would work too:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html" />
<xsl:key name="title-search" match="book" use="a[#n='author']"/>
<xsl:template match="/">
<HTML>
<BODY>
<xsl:for-each select="key('title-search', 'David Perry')">
<DIV>
<xsl:value-of select="a[#n='title']"/>
</DIV>
</xsl:for-each>
</BODY>
</HTML>
</xsl:template>
</xsl:stylesheet>
This is basic XSLT transformation, you can do something like this:
<xsl:template match="book">
<div>
Author: <xsl:value-of select="a[#n='author']/s" />
title: <xsl:value-of select="a[#n='title']/s" >
release: <xsl:value-of select="a[#n='release']/s" >
</div>
</xsl:template>

XSLT, I'm studying with my own XSLT example, but it doesn't work as I expected

First, my code is..
<?xml version="1.0" encoding="UTF-8"?>
<mpml>
<problem>
<context>
<p>두 다항식 $A=x^2 - xy + 2y^2$, $B=3x^2 + 2xy - y^2$에 대하여 $A-B$를 계산한 식이 $ax^2 +bxy + cy^2$일 때, 상수 $a+b+c$의 값은?</p>
</context>
<answerlist>
<i>-4</i>
<i>-2</i>
<i>0</i>
<i>2</i>
<i>4</i>
</answerlist>
</problem>
<problem>
<context>
<p>연립방정식 $\begin{cases} x+y+z=30 \\ 2x+3y+4z=93 \\ y=z+3 \end{cases}$의 해를 $x=a$, $y=b$, $z=c$라 할 때, $a-2b+3c$의 값은? (단, $a$, $b$, $c$는 실수.)</p>
</context>
<answerlist>
<i>7</i>
<i>9</i>
<i>11</i>
<i>13</i>
<i>15</i>
</answerlist>
</problem>
</mpml>
and it's xsl code is..
<?xml version="1.0" encoding="UTF-8"?>
<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<h2> Testing.. </h2>
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="problem">
<div class="problem">
<xsl:apply-templates select="context"/>
<xsl:apply-templates select="answerlist"/>
</div>
</xsl:template>
<xsl:template match="context">
<div class="context">
</div>
</xsl:template>
<xsl:template match="answerlist">
<div class="answerlist">
test answerlist
</div>
</xsl:template>
</xsl:transform>
In XSLT Tryit editor (thanks to w3school), above XSLT work as I expected. However when I tried this in my server, there is an 'extra content at the end of the document.' error and nothings shown except very first template.
I think the problem is that your XSLT does not produce well-formed XML in output: in the template <xsl:template match="/">, you should wrap content within a single root tag.
E.g.:
<xsl:template match="/">
<body>
<h2> Testing.. </h2>
<xsl:apply-templates/>
</body>
</xsl:template>

Determine the position of node using XSLT

Given the following XML:
<data>
<content>
<section link-id="32">
<entry id="9">
<title handle="apples">Apples</title>
</entry>
<entry id="1">
<title handle="oranges">Oranges</title>
</entry>
<entry id="4">
<title handle="pears">Pears</title>
</entry>
</section>
<section link-id="23">
<entry id="59">
<title handle="chevrolet">Chevrolet</title>
</entry>
<entry id="31">
<title handle="toyota">Toyota</title>
</entry>
<entry id="54">
<title handle="bmw">BMW</title>
</entry>
</section>
</content>
</data>
Styled by this XSL:
<xsl:template match="data">
<html>
<body>
<xsl:apply-templates select="content/section" />
</body>
</html>
</xsl:template>
<xsl:template match="content/section">
<ul>
<li>
Title: <xsl:value-of select="entry/title"/>
</li>
<li>
Position: <xsl:value-of select="position()"/>
</li>
</ul>
</xsl:template>
How would I display and integer representing the order (1-6) of the selected entry nodes? The expected values would be 1 and 4. The example shows values of 1 and 2, i.e. the position in the selected node set. What I want is the numeric position in the XML file, not the selection.
I am unclear exactly what you are asking about, as your "1 and 4" and reference to "position in the previous node set" is a bit confusing. But I think you have a couple options.
You can process all entries from the start:
<body>
<ul>
<xsl:apply-templates select="content/section/entry"/>
</ul>
</body>
...
<xsl:template match="entry">
<li>
Title: <xsl:apply-templates select="title"/>
</li>
<li>
Position: <xsl:apply-templates select="position()"/>
</li>
</xsl:template>
Or, if you find you have to process the sections and entries separately, then you'll find yourself inside of an entry with position() not helping. At this point you can use <xsl:number level="any"/>. If you are at a position deep inside of an entry, you can use <xsl:number count="entry" level="any"/>.
You are confusing "position" (an English word that describes what you want) with "position()" (an XPath function that gives you something quite different).
Try
<xsl:for-each select="entry[1]">
<xsl:number level="any" from="content"/>
</xsl:for-each>
It looks as if you are deliberately using the XSLT 1.0 "feature" whereby xsl:value-of applied to a node-set ignores all nodes except the first. If you want your code to be compatible with 2.0 (and understandable to the reader) it's best to make this explicit by writing select="entry[1]/title".

insert into cdata text from xml node usning xslt

My scenario is that we have to check for a div tag in the cdata of a body element. If div is present we have to insert the the text from node2 into the div tag.
This is my input xml:
<?xml version="1.0" encoding="utf-8"?>
<root>
<node1>abc</node1>
<node2> needs to replace inside cdata div</node2>
<body> <![CDATA[
<p>some text some textabcabcabcabc</p>
<div class="marginBottom_4px">
</div>
<p>some text some textabcabc</P>
]]>
</body>
</root>
The out put xml would be:
<?xml version="1.0" encoding="utf-8"?>
<div class="marginBottom_10px">
abc
</div>
<div class="marginBottom_5px">
<p>some text some textabcabcabcabc</p>
<div class="marginBottom_4px">
needs to replace inside cdata div
</div>
<p>some text some textabcabc</P>
</div>
My transform is:
<?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="xml" indent="yes"/>
<xsl:template match="/">
<xsl:value-of disable-output-escaping="yes" select ="$firstnode"/>
<xsl:text disable-output-escaping="yes"><![CDATA[ <div class="marginBottom_10px">
]]>
</xsl:text>
<xsl:value-of disable-output-escaping ="yes" select="root/body"/>
<xsl:text disable-output-escaping="yes"><![CDATA[
</div>
]]>
</xsl:text>
</xsl:template>
<xsl:variable name="firstnode">
<xsl:text disable-output-escaping="yes"><![CDATA[
<div class="marginBottom_10px">
]]>
</xsl:text>
<xsl:value-of disable-output-escaping ="yes" select="root/node1"/>
<xsl:text disable-output-escaping="yes"><![CDATA[
</div>
]]>
</xsl:text>
</xsl:variable>
</xsl:stylesheet>
I am able to produce the out put. but my xml is very complex like below:
<?xml version="1.0" encoding="utf-8" ?>
<ComplexXML>
<environment>
couple of nodes..
</environment>
<document>
nodes
</document>
<element cd="dsjdhfjk" input="abc.xml" mode="" >
<cd position="1">
<attributes>
<type>dummy text</type>
<title>dummy text</title>
</attributes>
<content>
<node2>
<![CDATA[
needs to replace inside cdata div
]]>
</node2>
<body>
<![CDATA[
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and scrambled it to make a type
specimen book </p>
<div class="marginBottom_4px">
</div>
<p>Lorem Ipsum is simply dummy text of her including versions of Lorem Ipsum. </p>
]]>
</body>
<abt >
<![CDATA[
text from abt node
]]>
</abt>
</content>
</cd>
</element>
</ComplexXML>
In the above xml I have to check for the abt node.If data is there in abt node the out should be like below:
<?xml version="1.0" encoding="UTF-8"?>
<div>
text from abt node
<div class="marginBottom_5px">
<p>Lorem Ipsum is simply dummy text of the printing and typesetting industry.
Lorem Ipsum has been the industry's standard dummy text ever since the 1500s,
when an unknown printer took a galley of type and scrambled it to make a type
specimen book </p>
**<div class="marginBottom_4px">
</div>** I need to remove this div tag and place the node2 content here.
<p>Lorem Ipsum is simply dummy text of her including versions of Lorem Ipsum. </p>
</div>
</div>
Sorry to bother you..I am very new to xslt..I am in learning stage only..Can you please guide me..
The following XSLT 1.0 stylesheet produces what I believe the desired output is, based upon the example output and comments. It relies upon the text in the CDATA of the input document being well-formed, and leverages disable-output-escaping:
<?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="xml" indent="yes"/>
<xsl:template match="node1">
<div class="marginBottom_10px">
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="node2" />
<xsl:template match="body">
<div class="marginBottom_5px">
<xsl:apply-templates/>
</div>
</xsl:template>
<xsl:template match="body/text()[contains(.,'<div') and contains(.,'</div>')]">
<xsl:value-of
disable-output-escaping="yes"
select="substring-before(.,'</div')" />
<xsl:value-of select="../../node2"/>
<xsl:value-of
disable-output-escaping="yes"
select="substring-after(.,substring-before(.,'</div'))" />
</xsl:template>
</xsl:stylesheet>
When applied against the example input, produces:
<?xml version="1.0" encoding="UTF-8"?>
<div class="marginBottom_10px">abc</div>
<div class="marginBottom_5px">
<p>some text some textabcabcabcabc</p>
<div class="marginBottom_4px">
needs to replace inside cdata div</div>
<p>some text some textabcabc</P>
</div>
Note: the output is not well-formed. There is no document element. You would likely want to create a template for the <root> to create a <div> or other containing element.
This version handles the other input format and generates what I believe the desired output is:
<?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="xml" indent="yes"/>
<!--rely on built-in templates,
which apply-templates to child nodes of elements
and get value-of for text() -->
<xsl:template match="content">
<xsl:choose>
<!-- if <abt> has a value, do the following -->
<xsl:when test="normalize-space(abt)">
<div>
<!-- apply templates to <abt>,
built-in template will copy text to output-->
<xsl:apply-templates select="abt"/>
<!-- apply templates to <body>, template defined below will handle it -->
<xsl:apply-templates select="body"/>
</div>
</xsl:when>
<xsl:otherwise>
<!--process child nodes -->
<xsl:apply-templates />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="node1">
<div class="marginBottom_10px">
<xsl:apply-templates/>
</div>
</xsl:template>
<!--empty template ensures that no content produced when templates applied to <node2>-->
<xsl:template match="node2" />
<xsl:template match="body">
<div class="marginBottom_5px">
<xsl:apply-templates/>
</div>
</xsl:template>
<!--Template for handling body/text() when <abt> does not have a value-->
<xsl:template match="*[not(normalize-space(abt))]/body/text()[contains(.,'<div') and contains(.,'</div>')]">
<!--get the value of content preceding "</div"-->
<xsl:value-of
disable-output-escaping="yes"
select="substring-before(.,'</div')" />
<!--get the value of <node2> -->
<xsl:value-of select="../../node2"/>
<!--get the value of content starting at "</div" -->
<xsl:value-of
disable-output-escaping="yes"
select="substring-after(.,substring-before(.,'</div'))" />
</xsl:template>
<!--Template for handling body/text() when <abt> does have a value -->
<xsl:template match="*[normalize-space(abt)]/body/text()[contains(.,'<div') and contains(.,'</div>')]">
<!--get the value preceding "<div" -->
<xsl:value-of
disable-output-escaping="yes"
select="substring-before(.,'>div')" />
<xsl:value-of select="../../node2"/>
<!--get the value following "</div>" -->
<xsl:value-of
disable-output-escaping="yes"
select="substring-after(.,'</div>')" />
</xsl:template>
</xsl:stylesheet>