364,085 Members | 5432 Browsing Online
Community for Developers & IT Professionals
Bytes IT Community

XSLT & String manipulation query

Bilal
P: n/a
Bilal
Hello,
I'm trying to perform some string manipulations in my stylesheet and
have gotten stuck on the issue below so hopefully can elicit some useful
hints.

Namely, the problem is that I need to convert an unqualified Xpath to
a fully qualified Xpath in an identity transform, i.e.

/AAA/BBB/CCC/@DDD

converted to

/ns:AAA/ns:BBB/ns:CCC/@DDD

with a predefined NS prefix and using a string tokenizer (adopted from
http://www.xslt.com/html/xsl-list/2005-04/msg00031.html) which returns
the tokens as:

<token>AAA</token>
<token>BBB</token>
<token>CCC</token>
<token>@DDD</token>

I'm assigning to the variable 'tokens' in the following template, which
then tries to produce the fully qualified namespace:

<xsl:template name="qualifiedXpath">
<xsl:param name="unqualifiedXpath"/>
<!-- -->
<xsl:variable name="sampleUnqualifiedXpath"
select="'/AAA/BBB/CCC/@DDD'"/>
<!-- hardcoded namespace prefix -->
<xsl:variable name="prefixString" select="'dns:'"/>
<!-- hardcoded delimiter character -->
<xsl:variable name="slash" select="'/'"/>
<!-- Variable to contain the tokens -->
<xsl:variable name="tokens">
<!-- Calling tokenizer template-->
<xsl:call-template name="tokenizer">
<xsl:with-param name="string" select="$sampleUnqualifiedXpath"/>
<xsl:with-param name="delimiter" select="$slash"/>
</xsl:call-template>
</xsl:variable>
<!-- Variable to hold the qualified Xpath -->
<xsl:variable name="qualXpath">
<!-- Constructing the qualified Xpath-->
<!-- Iterate through the returned token nodes -->
<xsl:for-each select="$tokens/token">
<!-- Add delimiter-->
<xsl:value-of select="$slash"/>
<!-- Add prefix only when token is an element name i.e. doesn't have the
@ character -->
<xsl:if test="not(contains(.,'@'))">
<!-- Adding namespace prefix -->
<xsl:value-of select="$prefixString"/>
<!-- Add token's value -->
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<!-- returning qualXpath variable -->
<xsl:value-of select="$qualXpath"/>
</xsl:template>

where the tokens' usage in the loop declaration
<xsl:for-each select="$tokens/token">

is causing a Result Tree Fragment (RTF) error; I've googled to find out
more about it but frankly don't understand the problem, and unsure what
an alternative solution would be and hence seeking Wisdom of The Elders!
:-)

BTW, the code snippet above might be buggy (hopefully not too much) as
I've been stuck at this RTF error and hence unable to proceed. I suspect
the usage of contains(.,'@'),
where I intend to check the token node's value for a '@' character, is
bit fishy. :)

Many thanks!

Regards,

Bilal B.





*** Sent via Developersdex http://www.developersdex.com ***
Oct 6 '06 #1
Share this Question
Share on Google+
10 Replies


Richard Tobin
P: n/a
Richard Tobin
In article <45264108$0$25785$815e3792@news.qwest.net>,
Bilal <nospam@devdex.comwrote:
><xsl:variable name="tokens">
><!-- Calling tokenizer template-->
><xsl:call-template name="tokenizer">
><xsl:with-param name="string" select="$sampleUnqualifiedXpath"/>
><xsl:with-param name="delimiter" select="$slash"/>
></xsl:call-template>
></xsl:variable>
Here you construct a result-tree fragment - the value of the variable
"tokens" is not a nodeset from the original document, but a
constructed nodeset.

In XSLT 1.0 you can't do much with result-tree fragments. In particular
you can't do this sort of thing:
><xsl:for-each select="$tokens/token">
Many XSLT processors have an extension function that allows you to convert
a result-tree fragment into an ordinary nodeset. For example, the
exsl:node-set() function may be available, see

http://www.exslt.org/exsl/functions/node-set/

-- Richard
Oct 6 '06 #2

Joe Kesselman
P: n/a
Joe Kesselman
As Richard implied, XSLT 2.0 (when it becomes official and more widely
available) removes that distinction between nodesets and result-tree
fragments.

If you don't want to rely on the extension function, the other 1.0
solution is to rewrite the tokenize-and-reconstruct process so it yields
the new string directly, rather than producing an RTF and then walking
that to produce the string. There are examples of recursive substring
replacement on the XSLT FAQ website, among many other places; it's a
fairly common idiom for functional languages like XSLT.

--
() ASCII Ribbon Campaign | Joe Kesselman
/\ Stamp out HTML e-mail! | System architexture and kinetic poetry
Oct 6 '06 #3

Bilal
P: n/a
Bilal
Hi Richard & Joe,
Thanks for the explanation and suggestions. Joe, based on your
suggestion, I started exploring other solution and I think I've come
across a search-and-replace method in my XSLT cookbook which does this
job. Now time to understand and customize it! ;-)

BTW, I'm sure I'm not the only one with procedural language experience
who has trouble with this functional language; its seems like a whole
different beast!

Many thanks for the help guys!

Regards,

Bilal B.



*** Sent via Developersdex http://www.developersdex.com ***
Oct 6 '06 #4

Dimitre Novatchev
P: n/a
Dimitre Novatchev
This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:testmap="testmap"
exclude-result-prefixes="xsl testmap"
>
<xsl:import href="str-map.xsl"/>

<!-- to be applied on any xml source -->

<testmap:testmap/>

<xsl:output omit-xml-declaration="yes" indent="yes"/>

<xsl:template match="/">
<xsl:variable name="vTestMap" select="document('')/*/testmap:*[1]"/>
<xsl:call-template name="str-map">
<xsl:with-param name="pFun" select="$vTestMap"/>
<xsl:with-param name="pStr"
select="substring-before('/AAA/BBB/CCC/@DDD', '/@')"/>
</xsl:call-template>
<xsl:value-of select=
"concat('/@', substring-after('/AAA/BBB/CCC/@DDD', '/@'))"/>
</xsl:template>

<xsl:template name="double" match="testmap:*">
<xsl:param name="arg1"/>

<xsl:value-of select="$arg1"/>
<xsl:if test="$arg1 = '/'">
<xsl:value-of select="'ns:'"/>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

when applied on any source xml document (not used),

produces the wanted result:

/ns:AAA/ns:BBB/ns:CCC/@DDD


Cheers,
Dimitre Novatchev

"Bilal" <nospam@devdex.comwrote in message
news:45264108$0$25785$815e3792@news.qwest.net...
Hello,
I'm trying to perform some string manipulations in my stylesheet and
have gotten stuck on the issue below so hopefully can elicit some useful
hints.
>
Namely, the problem is that I need to convert an unqualified Xpath to
a fully qualified Xpath in an identity transform, i.e.
>
/AAA/BBB/CCC/@DDD
>
converted to
>
/ns:AAA/ns:BBB/ns:CCC/@DDD
>
with a predefined NS prefix and using a string tokenizer (adopted from
http://www.xslt.com/html/xsl-list/2005-04/msg00031.html) which returns
the tokens as:
>
<token>AAA</token>
<token>BBB</token>
<token>CCC</token>
<token>@DDD</token>
>
I'm assigning to the variable 'tokens' in the following template, which
then tries to produce the fully qualified namespace:
>
<xsl:template name="qualifiedXpath">
<xsl:param name="unqualifiedXpath"/>
<!-- -->
<xsl:variable name="sampleUnqualifiedXpath"
select="'/AAA/BBB/CCC/@DDD'"/>
<!-- hardcoded namespace prefix -->
<xsl:variable name="prefixString" select="'dns:'"/>
<!-- hardcoded delimiter character -->
<xsl:variable name="slash" select="'/'"/>
<!-- Variable to contain the tokens -->
<xsl:variable name="tokens">
<!-- Calling tokenizer template-->
<xsl:call-template name="tokenizer">
<xsl:with-param name="string" select="$sampleUnqualifiedXpath"/>
<xsl:with-param name="delimiter" select="$slash"/>
</xsl:call-template>
</xsl:variable>
<!-- Variable to hold the qualified Xpath -->
<xsl:variable name="qualXpath">
<!-- Constructing the qualified Xpath-->
<!-- Iterate through the returned token nodes -->
<xsl:for-each select="$tokens/token">
<!-- Add delimiter-->
<xsl:value-of select="$slash"/>
<!-- Add prefix only when token is an element name i.e. doesn't have the
@ character -->
<xsl:if test="not(contains(.,'@'))">
<!-- Adding namespace prefix -->
<xsl:value-of select="$prefixString"/>
<!-- Add token's value -->
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<!-- returning qualXpath variable -->
<xsl:value-of select="$qualXpath"/>
</xsl:template>
>
where the tokens' usage in the loop declaration
<xsl:for-each select="$tokens/token">
>
is causing a Result Tree Fragment (RTF) error; I've googled to find out
more about it but frankly don't understand the problem, and unsure what
an alternative solution would be and hence seeking Wisdom of The Elders!
:-)
>
BTW, the code snippet above might be buggy (hopefully not too much) as
I've been stuck at this RTF error and hence unable to proceed. I suspect
the usage of contains(.,'@'),
where I intend to check the token node's value for a '@' character, is
bit fishy. :)
>
Many thanks!
>
Regards,
>
Bilal B.
>
>
>
>
>
*** Sent via Developersdex http://www.developersdex.com ***

Oct 7 '06 #5

Dimitre Novatchev
P: n/a
Dimitre Novatchev
Of course, the imported stylesheet is from the EXSLT-version of FXSL1.x

When one has such a toolset, solving such problems takes just two minutes.

Cheers,
Dimitre Novatchev

"Dimitre Novatchev" <dimitren@tpg.com.auwrote in message
news:452711e9$0$97218$892e7fe2@authen.yellow.readf reenews.net...
This transformation:
>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:testmap="testmap"
exclude-result-prefixes="xsl testmap"
>>
<xsl:import href="str-map.xsl"/>
>
<!-- to be applied on any xml source -->
>
<testmap:testmap/>
>
<xsl:output omit-xml-declaration="yes" indent="yes"/>
>
<xsl:template match="/">
<xsl:variable name="vTestMap" select="document('')/*/testmap:*[1]"/>
<xsl:call-template name="str-map">
<xsl:with-param name="pFun" select="$vTestMap"/>
<xsl:with-param name="pStr"
select="substring-before('/AAA/BBB/CCC/@DDD', '/@')"/>
</xsl:call-template>
<xsl:value-of select=
"concat('/@', substring-after('/AAA/BBB/CCC/@DDD', '/@'))"/>
</xsl:template>
>
<xsl:template name="double" match="testmap:*">
<xsl:param name="arg1"/>
>
<xsl:value-of select="$arg1"/>
<xsl:if test="$arg1 = '/'">
<xsl:value-of select="'ns:'"/>
</xsl:if>
</xsl:template>
>
</xsl:stylesheet>
>
when applied on any source xml document (not used),
>
produces the wanted result:
>
/ns:AAA/ns:BBB/ns:CCC/@DDD
>
>
Cheers,
Dimitre Novatchev
>
"Bilal" <nospam@devdex.comwrote in message
news:45264108$0$25785$815e3792@news.qwest.net...
>Hello,
> I'm trying to perform some string manipulations in my stylesheet and
>have gotten stuck on the issue below so hopefully can elicit some useful
>hints.
>>
> Namely, the problem is that I need to convert an unqualified Xpath to
>a fully qualified Xpath in an identity transform, i.e.
>>
>/AAA/BBB/CCC/@DDD
>>
>converted to
>>
>/ns:AAA/ns:BBB/ns:CCC/@DDD
>>
>with a predefined NS prefix and using a string tokenizer (adopted from
>http://www.xslt.com/html/xsl-list/2005-04/msg00031.html) which returns
>the tokens as:
>>
><token>AAA</token>
><token>BBB</token>
><token>CCC</token>
><token>@DDD</token>
>>
>I'm assigning to the variable 'tokens' in the following template, which
>then tries to produce the fully qualified namespace:
>>
><xsl:template name="qualifiedXpath">
><xsl:param name="unqualifiedXpath"/>
><!-- -->
><xsl:variable name="sampleUnqualifiedXpath"
>select="'/AAA/BBB/CCC/@DDD'"/>
><!-- hardcoded namespace prefix -->
><xsl:variable name="prefixString" select="'dns:'"/>
><!-- hardcoded delimiter character -->
><xsl:variable name="slash" select="'/'"/>
><!-- Variable to contain the tokens -->
><xsl:variable name="tokens">
><!-- Calling tokenizer template-->
><xsl:call-template name="tokenizer">
><xsl:with-param name="string" select="$sampleUnqualifiedXpath"/>
><xsl:with-param name="delimiter" select="$slash"/>
></xsl:call-template>
></xsl:variable>
><!-- Variable to hold the qualified Xpath -->
><xsl:variable name="qualXpath">
><!-- Constructing the qualified Xpath-->
><!-- Iterate through the returned token nodes -->
><xsl:for-each select="$tokens/token">
><!-- Add delimiter-->
><xsl:value-of select="$slash"/>
><!-- Add prefix only when token is an element name i.e. doesn't have the
>@ character -->
><xsl:if test="not(contains(.,'@'))">
><!-- Adding namespace prefix -->
><xsl:value-of select="$prefixString"/>
><!-- Add token's value -->
><xsl:value-of select="."/>
></xsl:if>
></xsl:for-each>
></xsl:variable>
><!-- returning qualXpath variable -->
><xsl:value-of select="$qualXpath"/>
></xsl:template>
>>
>where the tokens' usage in the loop declaration
><xsl:for-each select="$tokens/token">
>>
>is causing a Result Tree Fragment (RTF) error; I've googled to find out
>more about it but frankly don't understand the problem, and unsure what
>an alternative solution would be and hence seeking Wisdom of The Elders!
>:-)
>>
> BTW, the code snippet above might be buggy (hopefully not too much) as
>I've been stuck at this RTF error and hence unable to proceed. I suspect
>the usage of contains(.,'@'),
>where I intend to check the token node's value for a '@' character, is
>bit fishy. :)
>>
> Many thanks!
>>
>Regards,
>>
>Bilal B.
>>
>>
>>
>>
>>
>*** Sent via Developersdex http://www.developersdex.com ***
>
>

Oct 7 '06 #6

Bilal
P: n/a
Bilal
Hi Dimitre,
Thanks for your input; your first reply seemed interesting, but as you
pointed out it using EXSLT, which I can't use just yet as I'm limited to
XSLT 1.0 only.

Regards,

Bilal B.


*** Sent via Developersdex http://www.developersdex.com ***
Oct 9 '06 #7

Dimitre Novatchev
P: n/a
Dimitre Novatchev

"Bilal" <nospam@devdex.comwrote in message
news:452a07ce$0$25774$815e3792@news.qwest.net...
Hi Dimitre,
Thanks for your input; your first reply seemed interesting, but as you
pointed out it using EXSLT, which I can't use just yet as I'm limited to
XSLT 1.0 only.
>
Regards,
>
Bilal B.
Then you could use one of the three vendor-dependent versions of FXSL
1.x -- MSXML, Saxon or Xalan- dependent.

Cheers,
Dimitre Novatchev


Oct 10 '06 #8

Joe Kesselman
P: n/a
Joe Kesselman
Xalan does implement the EXSLT library, I believe.

--
() ASCII Ribbon Campaign | Joe Kesselman
/\ Stamp out HTML e-mail! | System architexture and kinetic poetry
Oct 10 '06 #9

Dimitre Novatchev
P: n/a
Dimitre Novatchev
I understood him to say he was not ready yet to use EXSLT, not that his XSLT
processor didn't support it.

Cheers,
Dimitre Novatchev


"Joe Kesselman" <keshlam-nospam@comcast.netwrote in message
news:ppCdnU115YX5u7bYnZ2dnUVZ_qOdnZ2d@comcast.com. ..
Xalan does implement the EXSLT library, I believe.
>
--
() ASCII Ribbon Campaign | Joe Kesselman
/\ Stamp out HTML e-mail! | System architexture and kinetic poetry

Oct 10 '06 #10

Bilal
P: n/a
Bilal
Yes, Dimitri rightly got what I intended! Although I am using Xalan-J,
but that is at the implementation end and I use XMLSpy for debugging
purposes (as thats the XML tool I'm most familiar with, and is used by
non-programmer colleagues :) and hence didn't want to rely on EXSLT etc.
as the latter doesn't support it AFAIK.

It's useful to know that Xalan does support EXSLT so I may use that
for future work.

Many thanks again!

Regards,

Bilal B.
>I understood him to say he was not ready yet to use EXSLT, >not that
his XSLT processor didn't support it.
>
>Cheers,
>Dimitre Novatchev
*** Sent via Developersdex http://www.developersdex.com ***
Oct 11 '06 #11

Post your reply

Help answer this question



Didn't find the answer to your .NET Framework question?

You can also browse similar questions: .NET Framework