Wrapping of elements - xslt

I have an input xml file that have multiple <b> elements, i have to wrap all <b> that are appearing continuously. i have written an xsl for this. it is better way to do this? also there are extra space generated during transformation after wrapping elements.
Sample Input XML
<chap>
<p><b>The</b> <b>Attorney</b> General <b>(Fees)</b><b>a</b><b>b</b><b>c</b> Determination 2012 No 110 commenced on 1 <b>July</b> <b>2012</b> <b>and</b> was repealed on <b>1</b> <b>July</b> <b>2013</b>. The Determination is yet to be amended by:</p>
</chap>
XSLT
<?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"
xmlns:guru="Self"
exclude-result-prefixes="xs"
version="2.0">
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
<xsl:template match="b[preceding-sibling::node()[1][self::b]]
|b[preceding-sibling::node()[1][normalize-space(.) = '']][preceding-sibling::node()[2][self::b]]"/>
<xsl:template match="b">
<xsl:copy>
<xsl:apply-templates/>
<xsl:if test="following-sibling::node()[1][self::b]">
<xsl:copy-of select="guru:wrap(following-sibling::node()[1], '')"/>
</xsl:if>
<xsl:if test="following-sibling::node()[1][normalize-space(.) = '']/following-sibling::node()[1][self::b]">
<xsl:copy-of select="guru:wrap(following-sibling::node()[2], following-sibling::node()[1])"/>
</xsl:if>
</xsl:copy>
</xsl:template>
<xsl:function name="guru:wrap">
<xsl:param name="b_data"/>
<xsl:param name="space"/>
<xsl:value-of select="$space"/>
<xsl:value-of select="$b_data"/>
<xsl:if test="$b_data/following-sibling::node()[1][self::b]">
<xsl:copy-of select="guru:wrap($b_data/following-sibling::node()[1], '')"/>
</xsl:if>
<xsl:if test="$b_data/following-sibling::node()[1][normalize-space(.) = '']/following-sibling::node()[1][self::b]">
<xsl:copy-of select="guru:wrap($b_data/following-sibling::node()[2], $b_data/following-sibling::node()[1])"/>
</xsl:if>
</xsl:function>
</xsl:stylesheet>
Output
<chap>
<p><b>The Attorney</b> General <b>(Fees)abc</b> Determination 2012 No 110 commenced on 1 <b>July 2012 and</b> was repealed on <b>1 July 2013</b> . The Determination is yet to be amended by:</p>
</chap>
Desired Output
<chap>
<p><b>The Attorney</b> General <b>(Fees)abc</b> Determination 2012 No 110 commenced on 1 <b>July 2012 and</b> was repealed on <b>1 July 2013</b>. The Determination is yet to be amended by:</p>
</chap>
Thanks in Advance.

I would suggest to use for-each-group group-adjacent="self::b or self::text()[. = ' ']":
<xsl:template match="p">
<xsl:copy>
<xsl:apply-templates select="#*"/>
<xsl:for-each-group select="node()" group-adjacent="self::b or self::text()[. = ' ']">
<xsl:choose>
<xsl:when test="current-grouping-key()">
<b>
<xsl:apply-templates select="current-group()/node() | current-group()[self::text()]"/>
</b>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="current-group()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
https://xsltfiddle.liberty-development.net/gWmuiHU/1 shows the result, it uses XSLT 3 but for XSLT 2 you simply have to remove the xsl:mode and keep the identity template
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>
you have in your code.

Related

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

XSLT – creating a network from all children elements

With XSLT 2.0, I am trying to create a list of relations between all children of given elements, in a document such as:
<doc>
<part1>
<name>John</name>
<name>Paul</name>
<name>George</name>
<name>Ringo</name>
<place>Liverpool</place>
</part1>
<part2>
<name>Romeo</name>
<name>Romeo</name>
<name>Juliet</name>
<fam>Montague</fam>
<fam>Capulet</fam>
</part2>
</doc>
The result I would like to obtain, ideally by conflating and weighing the identical relations, would be (in whatever order) something like:
<doc>
<part1>
<rel><name>John</name><name>Paul</name></rel>
<rel><name>John</name><name>George</name></rel>
<rel><name>John</name><name>Ringo</name></rel>
<rel><name>Paul</name><name>George</name></rel>
<rel><name>Paul</name><name>Ringo</name></rel>
<rel><name>George</name><name>Ringo</name></rel>
<rel><name>John</name><place>Liverpool</place></rel>
<rel><name>Paul</name><place>Liverpool</place></rel>
<rel><name>George</name><place>Liverpool</place></rel>
<rel><name>Ringo</name><place>Liverpool</place></rel>
</part1>
<part2>
<rel weight="2"><name>Romeo</name><name>Juliet</name></rel>
<rel weight="2"><name>Romeo</name><fam>Montague</fam></rel>
<rel weight="2"><name>Romeo</name><fam>Capulet</fam></rel>
<rel><name>Juliet</name><fam>Montague</fam></rel>
<rel><name>Juliet</name><fam>Capulet</fam></rel>
<rel><fam>Montague</fam><fam>Capulet</fam></rel>
</part2>
</doc>
—but I'm not sure how to proceed. Many thanks in advance for your help.
You still haven't explained the logic that needs to be applied here, so this is based largely on a guess:
XSLT 2.0
<xsl:stylesheet version="2.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="/">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="doc/*">
<!-- first pass-->
<xsl:variable name="unique-items">
<xsl:for-each-group select="*" group-by="concat(name(), '|', .)">
<item name="{name()}" count="{count(current-group())}" value="{.}"/>
</xsl:for-each-group>
</xsl:variable>
<!-- output -->
<xsl:copy>
<xsl:for-each select="$unique-items/item">
<xsl:variable name="left" select="."/>
<xsl:for-each select="following-sibling::item">
<xsl:variable name="weight" select="$left/#count * #count" />
<rel>
<xsl:if test="$weight gt 1">
<xsl:attribute name="weight" select="$weight"/>
</xsl:if>
<xsl:apply-templates select="$left | ." />
</rel>
</xsl:for-each>
</xsl:for-each>
</xsl:copy>
</xsl:template>
<xsl:template match="item">
<xsl:element name="{#name}">
<xsl:value-of select="#value"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
The idea here is to remove duplicates in the first pass, then enumerate all combinations in the second (final) pass. The weight is computed by multiplying the number of occurrences of each member of a combination pair and shown only when it exceeds 1.
At least the combinatoric part of your problem could be solved with the following XSLT script. It does not solve the elimination of duplicates, but that could possibly be done in a second transformation.
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!-- standard copy template -->
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*" />
</xsl:copy>
</xsl:template>
<xsl:template match="doc/*">
<xsl:copy>
<xsl:variable name="l" select="./*"/>
<xsl:for-each select="$l">
<xsl:variable name="a" select="."/>
<xsl:variable name="posa" select="position()"/>
<xsl:variable name="namea" select="name()"/>
<xsl:for-each select="$l">
<xsl:if test="position() > $posa and (. != $a or name() != $namea)">
<rel>
<xsl:copy-of select="$a"/>
<xsl:copy-of select="."/>
</rel>
</xsl:if>
</xsl:for-each>
</xsl:for-each>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
When applied to the first part of your example, this produces:
<part1>
<rel><name>John</name><name>Paul</name></rel>
<rel><name>John</name><name>George</name></rel>
<rel><name>John</name><name>Ringo</name></rel>
<rel><name>John</name><place>Liverpool</place></rel>
<rel><name>Paul</name><name>George</name></rel>
<rel><name>Paul</name><name>Ringo</name></rel>
<rel><name>Paul</name><place>Liverpool</place></rel>
<rel><name>George</name><name>Ringo</name></rel>
<rel><name>George</name><place>Liverpool</place></rel>
<rel><name>Ringo</name><place>Liverpool</place></rel>
</part1>
Which seems about correct. If have no idea if the duplicate elimination (or weighting, as you call it) could be done in the same transformation.

Rename a batch of values with xslt

We have a program that uses xml to save configurations of our program. Someone decided to rename a couple of values in our database and these renames should now also be backwards compatible in the configurations of our customers.
An example of a configuration
<configuration>
<fruitToEat>yellow_curved_thing</fruitToEat> <!-- should now become banana -->
</configuration>
A simple match would be (not tested, just an example):
<xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match"/configuration/fruitToEat/text()">
<xsl:text>banana</xsl:text>
</xsl:template>
</xsl:template>
But this is just one example and I want to do this 150 times.
Is it possible to make an xsl that reads a simple text file or ini file that tells me how the 150 matches should look alike?
<xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- recreate this template 150 times from an ini file or something -->
<xsl:template match"/configuration/fruitToEat/text()[.='yellow_curved_thing']">
<xsl:text>banana</xsl:text>
</xsl:template>
</xsl:template>
An example of my mapping file could be simply:
yellow_curved_thing = banana
round_thing = tomato
round_dotted = strawberry
And I would simply want a small xslt that tells me:
<xsl:template>
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<!-- recreate this template 150 times from an ini file or something -->
<xsl:template match"/configuration/fruitToEat/text()[.=$fileRow0]">
<xsl:text>$fileRow1</xsl:text>
</xsl:template>
</xsl:template>
So even if I think there is more complexity behind the curtain, may be this will help a little bit.
There are some possibilities to do this with xlst. Which would be best in long term depends on complexity in real life and how often you need to do this with different "mapping" information.
For your easy example you can put the "mapping" information into a xml file. This could be done by some script form ini file.
<mappings>
<mapping name="fruitToEat" >
<map from="yellow_curved_thing" to="banana" />
<map from="round_thing" to="tomato" />
<map from="round_dotted" to="strawberry" />
</mapping>
</mappings>
Than you can have a template which make use of this mapping information:
<xsl:variable name="fruitMapping"
select="document('fruitmapping.xml')//mapping[#name='fruitToEat']" />
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/configuration/fruitToEat/text()" >
<!-- find the entry in "ini file" -->
<xsl:variable name ="map" select="$fruitMapping/map[#from = current()]" />
<xsl:choose>
<xsl:when test="$map" >
<xsl:value-of select="$map/#to"/>
</xsl:when>
<xsl:otherwise>
<xsl:copy />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
But if this is a onetime job I would implement this "mapping" direct a template. Like this:
<xsl:template match="/configuration/fruitToEat/text()" >
<xsl:choose>
<xsl:when test=".='yellow_curved_thing'" >banana</xsl:when>
<xsl:when test=".='round_thing'" >tomato</xsl:when>
<xsl:when test=".='round_dotted'" >strawberry</xsl:when>
<xsl:otherwise>
<xsl:copy />
</xsl:otherwise>
</xsl:choose>
</xsl:template>
It seems you wanted to create your XSLT dynamic XSLT on the basis of your configuration file which is also an XML document. Have a look this exmple considering this:
configuration.xml
<p>
<configuration>
<fruitToEat>yellow_curved_thing</fruitToEat>
<mapped>banana</mapped>
</configuration>
<configuration>
<fruitToEat>round_thing</fruitToEat>
<mapped>tomato</mapped>
</configuration>
</p>
XSLT:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="xml" encoding="UTF-8" indent="yes" omit-xml-declaration="yes"/>
<xsl:template match="/">
<xsl:element name="xsl:stylesheet">
<xsl:attribute name="version">
<xsl:text>1.0</xsl:text>
</xsl:attribute>
<xsl:element name="xsl:template">
<xsl:attribute name="match">
<xsl:text>node()|#*</xsl:text>
</xsl:attribute>
<xsl:element name="xsl:copy">
<xsl:element name="xsl:apply-templates">
<xsl:attribute name="select">
<xsl:text>node()|#*</xsl:text>
</xsl:attribute>
</xsl:element>
</xsl:element>
</xsl:element>
<xsl:for-each select="//configuration">
<xsl:element name="xsl:template">
<xsl:attribute name="match">
<xsl:text>configuration/fruitToEat/text()[.=</xsl:text>
<xsl:text>'</xsl:text>
<xsl:value-of select="fruitToEat"/>
<xsl:text>']</xsl:text>
</xsl:attribute>
<xsl:element name="xsl:text">
<xsl:value-of select="mapped"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
output:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="node()|#*">
<xsl:copy>
<xsl:apply-templates select="node()|#*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="configuration/fruitToEat/text()[.='yellow_curved_thing']">
<xsl:text>banana</xsl:text>
</xsl:template>
<xsl:template match="configuration/fruitToEat/text()[.='round_thing']">
<xsl:text>tomato</xsl:text>
</xsl:template>
</xsl:stylesheet>

Replacing the namespace in input xml

I have two types of input xml, one with namespace prefix and another one without prefix and i want to replace the namespaces.
Sample1
<v1:Library xmlns:v1="http://testlibrary" xmlns:v2="http://commonprice">
<v1:Books_details>
<v1:Name>test1</v1:Name>
<v1:title>test2</v1:title>
<v2:price xmlns="http://commonprice">12</v2:price>
</v1:Books_details>
</v1:Library>
Sample2
<Library xmlns="http://testlibrary">
<Books_details>
<Name>test1</Name>
<title>test2</title>
<price xmlns="http://commonprice">12</price>
</Books_details>
</Library>
I have written following XSLT to change the namespace from "http://testlibrary" to "http://newlibrary" and it works fine for sample1 but it doesn't work for the sample2. It gives wrong result. It also the change the namespace of the price element even though it doesn't have namespace to be replaced.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:param name="old_namespace"/>
<xsl:param name="new_namespace"/>
<xsl:template match="/">
<xsl:apply-templates select="#* | node()"/>
</xsl:template>
<xsl:template match="text() | comment() | processing-instruction()">
<xsl:copy>
<xsl:apply-templates select="text() | comment() | processing-instruction()"/>
</xsl:copy>
</xsl:template>
<!-- Template used to copy elements -->
<xsl:template match="*">
<xsl:variable name="name">
<xsl:choose>
<xsl:when test="contains(name(), ':')">
<xsl:value-of select="name()"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="local-name()"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="{$name}" namespace="{$new_namespace}">
<!-- Copy all namespace through except for namespace to be changed -->
<xsl:for-each select="namespace::*">
<xsl:if test="string(.)!=$old_namespace">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:for-each>
<xsl:apply-templates select="node()|#*"/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
Note: My first answer was wrong because in XSLT 1.0, you can't use variable references within a match pattern.
This style-sheet will take either Sample1 or Sample2 as input document and replace all occurrences of the old namespace, from the element names, with the new namespace. Note: you can change the xsl:variable for xsl:param.
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:variable name="old_namespace" select="'http://testlibrary'" />
<xsl:variable name="new_namespace" select="'http://newlibrary'" />
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="*">
<xsl:choose>
<xsl:when test="namespace-uri()=$old_namespace">
<xsl:element name="{local-name()}" namespace="{$new_namespace}">
<xsl:apply-templates select="#*|node()"/>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Caveat
The above style-sheet will only change the namespace of the elements. It will not change the namespaces of attributes, nor will it remove extraneous namespaces nodes.
On a more specific solution
It is very unusual to require a general solution for an operation on a variable namespace. Namespaces, being what they are tend to be fixed and known. Consider carefully, if you really need a generalized solution. If you need a specific solution, meaning replacing occurrences of a specific namespace, then things get a lot easier, such as with this style-sheet...
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:old="http://testlibrary"
xmlns:new="http://newlibrary">
<xsl:template match="#*|node()">
<xsl:copy>
<xsl:apply-templates select="#*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="old:*">
<xsl:element name="{local-name()}" namespace="http://newlibrary">
<xsl:apply-templates select="#*|node()" />
</xsl:element>
</xsl:template>
</xsl:stylesheet>
UPDATE
I just noticed Dimitre's solution to a very similar question here.

xslt generate children based on split and parent node name

is it possible to do the following in xsl. I'm tring to split the contents of an element and create sub-elements based on the split. To make things trickier there are the occasional exception (ie node-4 doesn't get split). I'm wondering if there is a way i can do this without explicit splits hardcoded for each element. Again, not sure if this is possible. thanks for the help!
original XML:
<document>
<node>
<node-1>hello world1</node-1>
<node-2>hello^world2</node-2>
<node-3>hello^world3</node-3>
<node-4>hello^world4</node-4>
</node>
</document>
transformed XML
<document>
<node>
<node-1>hello world1</node-1>
<node-2>
<node2-1>hello</node2-1>
<node2-2>world2</node2-2>
</node-2>
<node-3>
<node3-1>hello</node3-1>
<node3-2>world3</node3-2>
</node-3>
<node-4>hello^world4</node-4>
</node>
</document>
To make things trickier there are the
occasional exception (ie node-4
doesn't get split). I'm wondering if
there is a way i can do this without
explicit splits hardcoded for each
element.
Pattern matching text nodes to tokenize, this more semantic stylesheet:
<xsl:stylesheet version="1.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="text()[contains(.,'^')]" name="tokenize">
<xsl:param name="pString" select="concat(.,'^')"/>
<xsl:param name="pCount" select="1"/>
<xsl:if test="$pString">
<xsl:element name="{translate(name(..),'-','')}-{$pCount}">
<xsl:value-of select="substring-before($pString,'^')"/>
</xsl:element>
<xsl:call-template name="tokenize">
<xsl:with-param name="pString"
select="substring-after($pString,'^')"/>
<xsl:with-param name="pCount" select="$pCount + 1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
<xsl:template match="node-4/text()">
<xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>
Output:
<document>
<node>
<node-1>hello world1</node-1>
<node-2>
<node2-1>hello</node2-1>
<node2-2>world2</node2-2>
</node-2>
<node-3>
<node3-1>hello</node3-1>
<node3-2>world3</node3-2>
</node-3>
<node-4>hello^world4</node-4>
</node>
</document>
Note: A classic tokenizer (In fact, this use a normalized string allowing empty items in sequence). Pattern matching and overwriting rules (preserving node-4 text node).
Here's an XSL 1.0 solution. I presume that the inconsistency in node-4 in your sample output was just a typo. Otherwise you'll have to define why node3 was split and node4 wasn't.
<?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" version="1.0">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<document>
<node>
<xsl:apply-templates select="document/node/*"/>
</node>
</document>
</xsl:template>
<xsl:template match="*">
<xsl:variable name="tag" select="name()"/>
<xsl:choose>
<xsl:when test="contains(text(),'^')">
<xsl:element name="{$tag}">
<xsl:element name="{concat($tag,'-1')}">
<xsl:value-of select="substring-before(text(),'^')"/>
</xsl:element>
<xsl:element name="{concat($tag,'-2')}">
<xsl:value-of select="substring-after(text(),'^')"/>
</xsl:element>
</xsl:element>
</xsl:when>
<xsl:otherwise>
<xsl:copy-of select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
This works as long as all the nodes you want split are at the same level, under /document/node. If the real document structure is different you will have to tweak the solution to match.
Can you use XSLT 2.0? If so, it sounds like <xsl:analyze-string> is right up your alley. You can split based on a regexp.
If you need further details, ask...
solution i used:
<xsl:output omit-xml-declaration="yes" method="xml" indent="yes"/>
<xsl:preserve-space elements="*"/>
<xsl:template match="node()|#*" name="identity">
<xsl:copy>
<xsl:apply-templates select="node()[1]|#*"/>
</xsl:copy>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>
<xsl:template match="node()" mode="copy">
<xsl:call-template name="identity"/>
</xsl:template>
<xsl:template match="node-2 | node-3" name="subFieldCarrotSplitter">
<xsl:variable name="tag" select="name()"/>
<xsl:element name="{$tag}">
<xsl:for-each select="str:split(text(),'^')">
<xsl:element name="{concat($tag,'-',position())}">
<xsl:value-of select="text()"/>
</xsl:element>
</xsl:for-each>
</xsl:element>
<xsl:apply-templates select="following-sibling::node()[1]"/>
</xsl:template>