Can we Create a Sequence in XSLT? - xslt

I am generating a text file using xslt.when i pass the xml input the xslt is converting the xml input as text file.can we provide the sequence number for each invocation.
and store it in some variable.
1)If suppose for the first time execution one text file is created so there is a variable inside the xslt (<sequence>) it should assign as number 1 like below
<sequence>1</sequence>
2)for the second time execution one more text file is created so the the sequence variable should increase.
<sequence>2<sequence>
3)for the third time execution one more text file is created so the sequence becomes like this
<sequence>3</sequence>
This thing we can generally do by create a sequence in oracle database and call that sequence inside the xslt and for each execution the sequence get increased
<sequence>CallOracleSequence</sequence>
can anyone please suggest with out using Oracle sequence.can we handle this inside the xslt.

The XSLT will not maintain state between executions of the transforms.
One option would be to leverage an external config file that contains the sequence number. Using an entity reference, you can make that XML config part of the XSLT document to read it's current value and when the XSLT executes, increment the number and overwrite the config file with the new sequence number using <xsl:result-document>.
Below is a working example of an XSLT 2.0 stylesheet that assumes there is a sequence file called sequence.xml in the same directory as the XSLT being executed:
<?xml version="1.0" encoding="UTF-8"?>
<!--delare entities to reference the sequence file-->
<!DOCTYPE xsl:stylesheet [
<!ENTITY sequenceFile SYSTEM "sequence.xml">
]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
<xsl:output name="sequenceOutput" method="xml" indent="yes"/>
<!--this variable is used to store the expanded entity reference for
the current sequence.xml file
When the XSLT is parsed it will "look" like this to the XML parser:
<xsl:variable name="sequence><sequence>1</sequence></xsl:variable>
-->
<xsl:variable name="sequence">
<!--
this entity reference will expand to:
<sequence>x</sequence>
when the XSLT is parsed
-->
&sequenceFile;
</xsl:variable>
<!--
Use the document() function with an empty value to read the XSLT
and then parse the sequence value produced by the entity reference
-->
<xsl:variable name="currentSequenceValue"
select="number(document('')/*/xsl:variable[#name='sequence']/sequence)"/>
<xsl:template match="/">
<!--do normal processing of the XML document-->
<xsl:apply-templates />
<!--
This will overwrite the sequence file with the incremented value
-->
<xsl:result-document format="sequenceOutput" href="sequence.xml">
<sequence><xsl:value-of select="$currentSequenceValue+1"/></sequence>
</xsl:result-document>
</xsl:template>
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>

Usually the sequence number will relate to something in the input, so you can use position() or xsl:number. But the details depend on the structure of the input.

This can be achieved with a single XSLT 2.0 transformation by writing out two files -- the result of the transformation and the updated number of executions:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema" exclude-result-prefixes="xs">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:variable name="vRepetitions" select=
"document('file:///c:/temp/delete/numberOfRepetitions.xml')/* +1"/>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/">
<xsl:result-document
href="file:///c:/temp/delete/iteration{$vRepetitions}.xml">
<xsl:apply-templates/>
</xsl:result-document>
<xsl:result-document href="file:///c:/temp/delete/numberOfRepetitions.xml">
<n><xsl:value-of select="$vRepetitions"/></n>
</xsl:result-document>
</xsl:template>
</xsl:stylesheet>
There are two files involved: the source XML document and an file containing the current number of executions -- the latter must be initially created to contain:
<n>0</n>
When the above transformation is applied on any source XML document (for this demo it just applies the identity rule on it), it does its usual processing and produces the wanted result. Additionally, the transformation reads the XML document that contains the current number of executuions and updates this number and writes the updated (number of executions) document back to disk:
Saxon 9.1.0.5J from Saxonica
Java version 1.6.0_31
Stylesheet compilation time: 625 milliseconds
Processing file:/C:/Program%20Files/Java/jre6/bin/marrowtr.xml
Building tree for file:/C:/Program%20Files/Java/jre6/bin/marrowtr.xml using class net.sf.saxon.tinytree.TinyBuilder
Tree built in 16 milliseconds
Tree size: 4 nodes, 4 characters, 0 attributes
Loading net.sf.saxon.event.MessageEmitter
Building tree for file:///c:/temp/delete/numberOfRepetitions.xml using class net.sf.saxon.tinytree.TinyBuilder
Tree built in 0 milliseconds
Tree size: 4 nodes, 1 characters, 0 attributes
Writing to file:/c:/temp/delete/iteration2.xml
Writing to file:/c:/temp/delete/numberOfRepetitions.xml
Execution time: 140 milliseconds
Memory used: 11477344
NamePool contents: 16 entries in 16 chains. 6 prefixes, 7 URIs
Here we see that at the second execution the transformation creates two files:
iteration2.xml contains the result from the second execution of the transformation.
numberOfRepetitions.xml If we examine this file, its contents after the second execution is as expected:
. . . .
<n>2</n>

Related

Find element that has both children and string in xslt

My source is:
<content>
<caption>text 1</caption>
<element1>Notepad is a basic text-editing program and it's most commonly used to view or edit text files. A text <bold>file</bold> is a <a>file</a> type typically identified by the .txt file name extension.</element1>
<section1>
<element2>Notepad is a basic text-editing program and it's most commonly used to view or edit text files. A text file is a file type typically identified by the .txt file name extension.</element2>
</section1>
</content>
I am trying to extract and create unique ID for the elements (it may be any element) which has both child (character elements) and text, and also the elements which has only text. The <bold> and <a> elements should not be seperated.
<caption id="id1">Text 1</caption>
<element1 id="id2">Notepad is a basic text-editing program and it's most commonly used to view or edit text files. A text <bold>file</bold> is a <a>file</a> type typically identified by the .txt file name extension.</element1>
<element2 id="id3">Notepad....</element2>
Any idea would be greatly appreciated...
I am not quite sure whether you want to preserve the hierarchy or whether you want to output a flat list of those elements you have described; the following simply extracts the described elements as a flat list (though preserving their content), the ids are generated by the XSLT processor:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
exclude-result-prefixes="xs">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="*[not(*) and text()[normalize-space()]] | *[* and text()[normalize-space()]]">
<xsl:copy>
<xsl:attribute name="id" select="generate-id()"/>
<xsl:apply-templates select="#* , node()" mode="copy"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*" mode="copy">
<xsl:copy>
<xsl:apply-templates select="#* , node()" mode="#current"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When applied to your input sample, Saxon 9 outputs
<?xml version="1.0" encoding="UTF-8"?>
<caption id="d1e2">text 1</caption>
<element1 id="d1e4">Notepad is a basic text-editing program and it's most commonly used to view or edit text files. A text <bold>file</bold> is a <a>file</a> type typically identified by the .txt file name extension.</element1>
<element2 id="d1e13">Notepad is a basic text-editing program and it's most commonly used to view or edit text files. A text file is a file type typically identified by the .txt file name extension.</element2>

How to "genericize" an XML-to-XML XSL transform to work with files having different tags but same basic structure

I have a set of XML files similar to this:
Example Input File:
<a-list>
<a-item key_field="unique1" other="foo"/>
<a-item key_field="unique2" other="foo"/>
...
</a-list>
and I have a transform that will merge these files into a single file of the same structure. It generates the same outer level element (<a-list>) containing all of the <a-item> elements from the files, and discards duplicate entities (entities having the same key_field). I am now faced with several other sets of files, each very similar in its top level structure, that I need to perform almost the same exact kind of merge.
For example, these files might look like this:
<b-list>
<b-item different_key_field="unique93" other="foo"/>
<b-item different_key_field="unique94" other="foo"/>
...
</b-list>
These other files have different data in them, but the transform is generically the same: I need to take multiple input files that have the same structure (a root level containing a list of items, where the items are uniquely identified by a key attribute), and produce an output file that has the top level element containing all of the (unique) items from each of the input files.
Unfortunately, my "merge" transform operates specifically on the named elements in the input files (e.g. it has templates for <a-item> nodes, and it specifically looks for duplicated key_field attributes). It is fairly trivial to copy the transform, search/replace the element names and the key attribute name, but it seems horribly inefficient to duplicate the same code once for each type of input file. The only things that are different are the name of the root element, the name of the item element, and the name of the key attribute. What I want to do (merge) remains the same.
How can I write a transformation that can perform this kind of merge operation without specifying the exact names of the elements/attribute, so that I can invoke the same transform for each type of file? Is there any way to accept the root element name, item element name, and key attribute name as parameters?
As additional constraints, I'm limited to using Xalan, so I believe that means XSL 1.0 only, and it would be best to avoid any extensions.
I thought about transforming an XSL with another XSL, but that seems rather convoluted for such a simple thing.
I've tried searching here and around the internet via Google, but I'm somewhat new to XSL, and all of the words I can think to search in association with XSL or XSLT seem to have specific meanings in the XSL context that make them less useful as search terms (e.g. XSL template, generic XSL, etc.). Some vocab and some good links would be great, an example would be amazing.
Many Thanks,
Russ
Here is a complete solution:
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:param name="pDoc1File" select="'b-list-file1.xml'"/>
<xsl:param name="pDoc2File" select="'b-list-file2.xml'"/>
<xsl:param name="pElemName" select="'b-item'"/>
<xsl:param name="pKeyAttrName" select="'different_key_field'"/>
<xsl:variable name="vDoc1" select="document($pDoc1File)"/>
<xsl:variable name="vDoc2" select="document($pDoc2File)"/>
<xsl:template match="/">
<xsl:apply-templates select="$vDoc1/node()"/>
</xsl:template>
<xsl:template match="/*">
<xsl:copy>
<xsl:copy-of select="#*"/>
<xsl:copy-of select=
"*[name()=$pElemName]
[not(#*[name()=$pKeyAttrName]
=
$vDoc2/*/*[name()=$pElemName]
/#*[name()=$pKeyAttrName])
]"/>
<xsl:copy-of select=
"$vDoc2/*/*[name()=$pElemName]
[not(#*[name()=$pKeyAttrName]
=
$vDoc1/*/*[name()=$pElemName]
/#*[name()=$pKeyAttrName])
]"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
File: b-list-file1.xml
<b-list>
<b-item different_key_field="unique93" other="foo"/>
<b-item different_key_field="unique94" other="foo"/> ...
</b-list>
File: b-list-file2.xml
<b-list>
<b-item different_key_field="unique92" other="foo"/>
<b-item different_key_field="unique93" other="foo"/> ...
</b-list>
When this transformation is applied on any XML document (not used / ignored), the wanted, correct result is produced:
<b-list>
<b-item different_key_field="unique94" other="foo"/>
<b-item different_key_field="unique92" other="foo"/>
</b-list>
Explanation:
The filepaths (URLs) to the documents to be processed are provided as global (external to the transformation) parameters.
The name of the elements is provided in a global parameter.
The name of the "key" attribute is provided as a global/external parameter.
Finally, the XPath expressions in the select attributes of the two <xsl:copy-of> instructions, use the values of the parameters for selecting the appropriately-named elements and attributes.
Do note: Every XSLT processor has its own implementation of setting and passing parameters to the transformation. Read this in the Xalan documentation.
Well you can solve your problem with parameters. There is no notion of templated xsl like C++ templates for example, but with parameters you can achieve this effect. For example one of my xslt files looks like this :
<xsl:stylesheet xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xml:space="preserve" version="2.0">
<!--Output type to be used with the xsl:result-document-->
<xsl:output name="html" encoding="utf-8" method="html" indent="yes" doctype- system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/>
<!--Global output type-->
<xsl:output encoding="utf-8" method="html" indent="yes" doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" doctype-public="-//W3C//DTD XHTML 1.0 Transitional//EN"/>
<!--xml output-->
<xsl:output name="xml" encoding="utf-8" method="xml" indent="yes"/>
<xsl:param name="sapFile" as="xs:string" required="yes"/>
<xsl:param name="automaticDate" as="xs:string" required="yes"/>
<xsl:param name="generatePDF" as="xs:string" required="yes"/>
<xsl:param name="fileName" as="xs:string" required="yes"/>
.
.
.
The important element here is xsl:param. You can pass these parameter when you "call" your xsl transform. These parameters in your case would be for example : in one case a-list and in the other case b-list etc. Then you can use these parameters like $param wherever you want in your xslt code so that you can achieve genericity.
I hope that give you some pointers :)

Best approach for combining several XSLT 1.0 passes which process the same nodes

I'm doing some very complex XSLT 1.0 transformation (currently using 8 XSLT passes). I want to combine this 8 passes without merging them in one file (this would be too complex). My solution would be using xsl:include and exsl:node-set to merge the passes and store temporary results in variables.
But I have one problem: My transformation passes copies most of the nodes and modifying only certain aspects. Therefore I need to process the same nodes in every pass, but with different xsl:template! But how do I do that? How to tell that after the first pass I want to apply templates from other XSLT stylesheet?
Very simplified example what I'm currently doing (2 XSLT passes):
Source:
<h>something here</h>
After XSLT pass 1:
<h someattribute="1">something here</h>
After XSLT pass 2:
<h someattribute="1" somemoreattribute="2">something here, and even more</h>
My current approach is to call the XSLT processor twice and saving the results temporary on disk:
xsltproc stylesheet1.xsl input.xml >temp.xml
xsltproc stylesheet2.xsl temp.xml >finalresult.xml
One possible solution would be to change each of the stylesheets to use a distinct mode. Then you could import them all to your master stylesheet and do multiple passes by applying templates using each mode in turn:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl"
version="1.0">
<xsl:import href="stylesheet1.xsl"/> <!-- assuming mode="stylesheet1" -->
<xsl:import href="stylesheet2.xsl"/> <!-- assuming mode="stylesheet2" -->
<xsl:import href="stylesheet3.xsl"/> <!-- assuming mode="stylesheet3" -->
<xsl:template match="/">
<xsl:variable name="temp1">
<xsl:apply-templates select="." mode="stylesheet1"/>
</xsl:variable>
<xsl:variable name="temp2">
<xsl:apply-templates mode="stylesheet2" select="exsl:node-set($temp1)"/>
</xsl:variable>
<xsl:apply-templates mode="stylesheet3" select="exsl:node-set($temp2)"/>
</xsl:template>
</xsl:stylesheet>
The downside is that you need to modify the original stylesheets, adding appropriate mode attributes to each xsl:templateand xsl:apply-templates. You can still make the stylesheets also work independently by adding an extra template like this in each of them:
<xsl:template match="/">
<xsl:apply-templates select="." mode="stylesheet1"/>
</xsl:template>
Why not use
<xsl:param name="iteration"/>
And pass the iteration number to the stylesheet? You can then use it like this
<xsl:if test="$iteration = 1">
...
</xsl:if>
...or in other contexts
You can set the parameter with
javax.xml.transform.Transformer.setParameter("iteration", 1);
Or with ant:
<xslt ...>
<param name="iteration" expression="1"/>
</xslt>

XSLT: need alternative to document()-function for multi-source processing

I'm adapting an XSLT from a third party which transforms an arbitrary number of XMLs into a single HTML document. It's a pretty complex script and it will be revised in the future, so I'm trying to do a minimal adaptation in order to get it to work for our needs.
The following is a stripped down version of the XSLT (containing the essentials):
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="http://www.w3.org/1999/xhtml">
<xsl:output method="text" encoding="UTF-8" omit-xml-declaration="yes"/>
<xsl:param name="files" select="document('files.xml')//File"/>
<xsl:param name="root" select="document($files)"/>
<xsl:template match="/">
<xsl:for-each select="$root/RootNode">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:template>
<xsl:template match="RootNode">
<xsl:for-each select="//Node">
<xsl:text>Node: </xsl:text><xsl:value-of select="."/><xsl:text>, </xsl:text>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Now files.xml contains a list of all the URLs of the files to be included (in this case the local files file1.xml and file2.xml). Because we want to read XMLs from memory rather than from disk, and because the invocation of the XSLT only allows for a single XML source, I have combined the two files in a single XML document. The following is a combination of two files (there may be more in a real situation)
<?xml version="1.0" encoding="UTF-8"?>
<TempNode>
<RootNode>
<Node>1</Node>
<Node>2</Node>
</RootNode>
<RootNode>
<Node>3</Node>
<Node>4</Node>
</RootNode>
</TempNode>
where the first RootNode originally resided in file1.xml and the second in file2.xml.
Due to the complexity of the actual XSLT, I've figured that my best shot is to try to alter the $root-param. I've tried the following:
<xsl:param name="root" select="/TempNode"/>
The problem is this. In the case of <xsl:param name="root" select="document($files)"/>, the XPath expression "//Node" in <xsl:for-each select="//Node"> selects the Node's from file1.xml and file2.xml independently, i.e. producing the following (desired) list:
Node: 1, Node: 2, Node: 3, Node: 4,
However, when I combine the content of the two files into a single XML and parse this (and use the suggested $root-definition), the expression "//Node" will select all Node's that are children of the TempNode. (In other words, the desired list, as represented above, is produced twice due to the combination with the outer <xsl:for-each select="$root/RootNode"> loop.)
(A side note: as observed in comment a) in this page, document() apparently changes the root node, perhaps explaining this behavior.)
My question becomes:
How can I re-define $root, using the combined XML as source instead of a multi-source through document(), so that the list is only produced once, without touching the remainder of the XSLT? It's like if $root defined using the document()-function, there is no common root node in the param. Is it possible to define a param with two "separate" node trees?
Btw: I've tried defining a document like this
<xsl:param name="root">
<xsl:for-each select="/TempNode/*">
<xsl:document>
<xsl:copy-of select="."/>
</xsl:document>
</xsl:for-each>
</xsl:param>
thinking it might solve the problem, but the "//Node" expression still fetches all the Nodes. Is the context node in the <xsl:template match="RootNode">-template actually somewhere in the input document and not the param? (Honestly, I'm pretty confused when it comes to context nodes.)
Thanks in advance!
(Updated more)
OK, some of the problem is becoming clear. First, just to make sure I understand, you aren't actually passing parameters for $files and $root to the XSLT processor invocation, right? (They might as well be variables rather than params?)
Now to the main issues... In XPath, when you evaluate an expression that begins with "/" (including "//"), the context node is ignored [mostly]. Therefore, when you have
<xsl:template match="RootNode">
<xsl:for-each select="//Node">
the matched RootNode is ignored. Maybe you wanted
<xsl:template match="RootNode">
<xsl:for-each select=".//Node">
in which the for-each would select Node elements that are descendants of the matched RootNode? This would fix your problem of generating the desired node list twice.
I inserted [mostly] above because I recalled that an "absolute location path" starts from "the root node of the document containing the context node". So the context node does affect what document is used for "//Node". Maybe that's what you intended all along? I guess I was slow to catch on to that.
(A side note: as observed in comment
a) in this page, document() apparently
changes the root node, perhaps
explaining this behavior.)
Or more precisely,
An absolute location path ["/..."]
followed by a relative location
path... selects the set of nodes that
would be selected by the relative
location path relative to the root
node of the document containing the
context node.
document() doesn't actually change anything, in the sense of side effects; rather, it returns a set of nodes contained (usually) by different documents than the primary source document. XSLT instructions like xsl:apply-templates and xsl:for-each establish new values for the context node inside the scope of their template bodies. So if you use xsl:apply-templates and xsl:for-each with select="document(...)/...", the context node inside the scope of those instructions will belong to an external document, so any use of "/..." as an XPath will start from that external document.
Updated again
How can I re-define $root, using the
combined XML as source instead of a
multi-source through document(), so
that the list is only produced once,
without touching the remainder of the
XSLT?
As #Alej hinted, it's really not possible given the above constraint. If you're selecting "//Node" in each iteration of the loop over "$root/RootNode", then in order for each iteration not to select the same nodes as the other iterations, each value of "$root/RootNode" must be in a different document. Since you're using the combined XML source, instead of a multi-source, this is not possible.
But if you don't insist that your <xsl:for-each select="//..."> XPath expression cannot change, it becomes very easy. :-) Just put a "." before the "//".
It's like if $root defined using the document()-function, there is no common root node
in the param.
The value of the param is a node-set. All nodes in the set may be contained in the same document, or they may not, depending on whether the first argument to document() is a nodeset or just a single node.
Is it possible to define a param with two "separate" node trees?
I believe by "separate", you mean "belonging to different documents"? Yes it is, but I don't think you can do it in XSLT 1.0 unless you're selecting nodes that belong to different documents in the first place.
You mentioned trying
<xsl:param name="root">
<xsl:for-each select="/TempNode/*">
<xsl:document>
<xsl:copy-of select="."/>
</xsl:document>
</xsl:for-each>
</xsl:param>
but <xsl:document> is not defined in XSLT 1.0, and your stylesheet says version="1.0". Do you have XSLT 2.0 available? If so, let us know and we can pursue this option. To be honest, <xsl:document> is not familiar territory for me. But I'm happy to learn along with you.
You can apply only nodes you need:
Input:
<?xml version="1.0" encoding="UTF-8"?>
<TempNode>
<RootNode>
<Node>1</Node>
<Node>2</Node>
</RootNode>
<RootNode>
<Node>3</Node>
<Node>4</Node>
</RootNode>
</TempNode>
<?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="/">
<xsl:copy>
<xsl:apply-templates select="TempNode/RootNode"/>
</xsl:copy>
</xsl:template>
<xsl:template match="RootNode">
<xsl:value-of select="concat('RootNode-', generate-id(.), '
')"/>
<xsl:apply-templates select="Node"/>
</xsl:template>
<xsl:template match="Node">
<xsl:value-of select="concat('Node', ., '
')"/>
</xsl:template>
</xsl:stylesheet>
Output:
RootNode-N65540
Node1
Node2
RootNode-N65549
Node3
Node4

Using xslt to alter nodes from a copied xml file

I would like to copy and alter data from another xml data. I have in addition to the normal two input xml files an extra xml file. I would like to embed the entire content of this xml file into my output xml and then change some aspect of it. I have managed to do this by copying the entire file into the right area as desired thus (Thanks to this post here):
<test>
<xsl:copy-of select="document('filename.xml')/*"/>
</test>
Problem is, I want to change some of the data in filename and I don't know how I can get this done. Something along this line, perhaps?
<xsl:template match="document('filename.xml')/root/elemntToBeChanged">
<xsl:apply-templates select="Test/changeItToThis"/>
Try This,
XSLT 2.0:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="#*|node()">
<xsl:copy><xsl:apply-templates select="#*|node()"/></xsl:copy>
</xsl:template>
<xsl:template match="root"><!--Input document's root element -->
<xsl:copy><xsl:apply-templates select="*|document('External-Doc.xml')"/></xsl:copy><!--Extrenal document called here -->
</xsl:template>
</xsl:stylesheet>