469,332 Members | 6,650 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 469,332 developers. It's quick & easy.

XSLT - Extracting name-value pairs

Let's suppose I have some nodes in an XML file, with an URL attribute:

<node url="mypage.php?name1=value1&foo=bar&foo2=bar2&nam e2=value0" />
<node url="myotherpage.php?name4=value4&foo=bar3&foo2=ba r5&name2=value8" />

and so on.

Let's suppose I want to retrieve this @url parameter, BUT ONLY with the
values, in querystring, associated with "foo" and "foo2" (thus
discarding name1, name2, name4 and every other different ones).

In other words, I must obtain:

mypage.php?foo=bar&foo2=bar2
myotherpage.php?&foo=bar3&foo2=bar5
.... and so on.

Is there a convenient way, in a transformation with XSL, to obtain this
string manipulation? (I'd prefer to stick to XSLT1.0, if possible)

Thanks in advance for your help.
Nov 7 '08 #1
11 4163
Ebenezer wrote:
Let's suppose I have some nodes in an XML file, with an URL attribute:

<node url="mypage.php?name1=value1&foo=bar&foo2=bar2&nam e2=value0" />
<node url="myotherpage.php?name4=value4&foo=bar3&foo2=ba r5&name2=value8" />

and so on.

Let's suppose I want to retrieve this @url parameter, BUT ONLY with the
values, in querystring, associated with "foo" and "foo2" (thus
discarding name1, name2, name4 and every other different ones).

In other words, I must obtain:

mypage.php?foo=bar&foo2=bar2
myotherpage.php?&foo=bar3&foo2=bar5
... and so on.

Is there a convenient way, in a transformation with XSL, to obtain this
string manipulation? (I'd prefer to stick to XSLT1.0, if possible)
Well
substring-before(node/@url, '?')
would give you the file name, the query string would need to be parsed
which needs a recursive template or an extension function in XSLT 1.0.
In XSLT 2.0 you could use the tokenize function and/or xsl:analyze-string:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/2008/mf"
exclude-result-prefixes="xsd mf"
version="2.0">

<xsl:function name="mf:get-query" as="xsd:string">
<xsl:param name="qs" as="xsd:string"/>
<xsl:param name="params" as="xsd:string*"/>
<xsl:variable name="filtered-qs" as="xsd:string*">
<xsl:for-each select="tokenize($qs, '&amp;')">
<xsl:analyze-string
select="."
regex="({string-join($params, '|')})=\w*">
<xsl:matching-substring>
<xsl:sequence select="regex-group(0)"/>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:for-each>
</xsl:variable>
<xsl:sequence select="string-join($filtered-qs, '&amp;')"/>
</xsl:function>

<xsl:template match="node">
<xsl:value-of select="concat(substring-before(@url, '?'), '?',
mf:get-query(substring-after(@url, '?'), ('foo', 'foo2')))"/>
</xsl:template>

</xsl:stylesheet>
--

Martin Honnen
http://JavaScript.FAQTs.com/
Nov 7 '08 #2

Thanks a lot for sharing and helping, Martin, your information is so
valuable, I'll carefully study your code.

Martin Honnen ha scritto:
Ebenezer wrote:
>Let's suppose I have some nodes in an XML file, with an URL attribute:

<node url="mypage.php?name1=value1&foo=bar&foo2=bar2&nam e2=value0" />
<node
url="myotherpage.php?name4=value4&foo=bar3&foo2=b ar5&name2=value8" />

and so on.

Let's suppose I want to retrieve this @url parameter, BUT ONLY with
the values, in querystring, associated with "foo" and "foo2" (thus
discarding name1, name2, name4 and every other different ones).

In other words, I must obtain:

mypage.php?foo=bar&foo2=bar2
myotherpage.php?&foo=bar3&foo2=bar5
... and so on.

Is there a convenient way, in a transformation with XSL, to obtain
this string manipulation? (I'd prefer to stick to XSLT1.0, if possible)

Well
substring-before(node/@url, '?')
would give you the file name, the query string would need to be parsed
which needs a recursive template or an extension function in XSLT 1.0.
In XSLT 2.0 you could use the tokenize function and/or xsl:analyze-string:

<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/2008/mf"
exclude-result-prefixes="xsd mf"
version="2.0">

<xsl:function name="mf:get-query" as="xsd:string">
<xsl:param name="qs" as="xsd:string"/>
<xsl:param name="params" as="xsd:string*"/>
<xsl:variable name="filtered-qs" as="xsd:string*">
<xsl:for-each select="tokenize($qs, '&amp;')">
<xsl:analyze-string
select="."
regex="({string-join($params, '|')})=\w*">
<xsl:matching-substring>
<xsl:sequence select="regex-group(0)"/>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:for-each>
</xsl:variable>
<xsl:sequence select="string-join($filtered-qs, '&amp;')"/>
</xsl:function>

<xsl:template match="node">
<xsl:value-of select="concat(substring-before(@url, '?'), '?',
mf:get-query(substring-after(@url, '?'), ('foo', 'foo2')))"/>
</xsl:template>

</xsl:stylesheet>

Nov 7 '08 #3
Ebenezer schrieb:
Let's suppose I have some nodes in an XML file, with an URL attribute:

<node url="mypage.php?name1=value1&foo=bar&foo2=bar2&nam e2=value0" />
<node url="myotherpage.php?name4=value4&foo=bar3&foo2=ba r5&name2=value8" />
If you have this, it's not XML. Instead of '&' in the url attribute
value, write '&amp;'.

--
Johannes Koch
In te domine speravi; non confundar in aeternum.
(Te Deum, 4th cent.)
Nov 8 '08 #4

"Ebenezer" <va*********@spam.comwrote in message
news:5j********************@twister1.libero.it...
Let's suppose I have some nodes in an XML file, with an URL attribute:

<node url="mypage.php?name1=value1&foo=bar&foo2=bar2&nam e2=value0" />
<node url="myotherpage.php?name4=value4&foo=bar3&foo2=ba r5&name2=value8"
/>

and so on.

Let's suppose I want to retrieve this @url parameter, BUT ONLY with the
values, in querystring, associated with "foo" and "foo2" (thus discarding
name1, name2, name4 and every other different ones).

In other words, I must obtain:

mypage.php?foo=bar&foo2=bar2
myotherpage.php?&foo=bar3&foo2=bar5
... and so on.

Is there a convenient way, in a transformation with XSL, to obtain this
string manipulation? (I'd prefer to stick to XSLT1.0, if possible)

Thanks in advance for your help.
Using FXSL 1.x and its "str-split-to-words" template, such processing is
trivial.

This transformation:

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:ext="http://exslt.org/common"
exclude-result-prefixes="ext"
>
<xsl:import href="strSplit-to-Words.xsl"/>

<!-- To be applied upon: testTokenize2.xml -->

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

<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>

<xsl:template match="@url">
<xsl:attribute name="{name()}">
<xsl:variable name="vHdUrl" select=
"substring-before(.,'?')"
/>
<xsl:variable name="vTlUrl" select=
"substring-after(.,'?')"
/>

<xsl:variable name="vFilteredActions">
<xsl:call-template name="filterActions">
<xsl:with-param name="pInput" select="$vTlUrl"/>
<xsl:with-param name="pMustStart" select="'foo'"/>
</xsl:call-template>
</xsl:variable>

<xsl:value-of select=
"concat($vHdUrl,'?',$vFilteredActions)"
/>
</xsl:attribute>
</xsl:template>

<xsl:template name="filterActions">
<xsl:param name="pInput"/>
<xsl:param name="pMustStart" select="'x'"/>

<xsl:variable name="vTokens">
<xsl:call-template name="str-split-to-words">
<xsl:with-param name="pStr" select="$pInput"/>
<xsl:with-param name="pDelimiters" select="'&amp;'"/>
</xsl:call-template>
</xsl:variable>

<xsl:for-each select=
"ext:node-set($vTokens)/word
[starts-with(.,$pMustStart)]"
>
<xsl:variable name="vactDelim">
<xsl:if test="position() 1">&amp;</xsl:if>
</xsl:variable>

<xsl:value-of select="concat($vactDelim, .)"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

when applied on this xml document:

<nodes>
<node
url="mypage.php?name1=value1&amp;foo=bar&amp;foo2= bar2&amp;name2=value0" />
<node
url="myotherpage.php?name4=value4&amp;foo=bar3&amp ;foo2=bar5&amp;name2=value8"
/>
</nodes>

produces the wanted results:

<nodes>
<node url="mypage.php?foo=bar&amp;foo2=bar2"/>
<node url="myotherpage.php?foo=bar3&amp;foo2=bar5"/>
</nodes>

Hope this helped.

Cheers,
Dimitre Novatchev
Nov 8 '08 #5
Johannes Koch ha scritto:
Ebenezer schrieb:
>Let's suppose I have some nodes in an XML file, with an URL attribute:

<node url="mypage.php?name1=value1&foo=bar&foo2=bar2&nam e2=value0" />
<node
url="myotherpage.php?name4=value4&foo=bar3&foo2=b ar5&name2=value8" />

If you have this, it's not XML. Instead of '&' in the url attribute
value, write '&amp;'.
Of course, but the parser I use won't bother on that.
Nov 8 '08 #6
Dimitre Novatchev ha scritto:
"Ebenezer" <va*********@spam.comwrote in message
news:5j********************@twister1.libero.it...
Using FXSL 1.x and its "str-split-to-words" template, such processing is
trivial.
Unfortunately, I use another engine.
Nov 8 '08 #7

"Ebenezer" <va*********@spam.comwrote in message
news:AA********************@twister1.libero.it...
Dimitre Novatchev ha scritto:
>"Ebenezer" <va*********@spam.comwrote in message
news:5j********************@twister1.libero.it. ..
Using FXSL 1.x and its "str-split-to-words" template, such processing is
trivial.

Unfortunately, I use another engine.
Hmm... Did I say that a specific "engine" was necessary for the solution?

FXSL 1.x works with *any* XSLT 1.0 processor that supports the
exsl:node-set() extension function.

There are 3 separate versions for MSXML, Xalan and Saxon, although the last
two XSLT 1.0 processors implement exsl:node-set().

For MSXML, there is a way to implement exslt:node-set() (and in any XSLT
processor that supports extension functions written in inline-JavaScript).
See:

http://www.jenitennison.com/blog/node/24

Lastly, FXSL 2.0 is the latest (since the last 4-5 years) version of FXSL
which is written in and for XSLT 2.0. It doesn't use any extension functions
at all.
Nov 9 '08 #8

"Ebenezer" <va*********@spam.comwrote in message
news:4A********************@twister1.libero.it...
Johannes Koch ha scritto:
>Ebenezer schrieb:
>>Let's suppose I have some nodes in an XML file, with an URL attribute:

<node url="mypage.php?name1=value1&foo=bar&foo2=bar2&nam e2=value0" />
<node url="myotherpage.php?name4=value4&foo=bar3&foo2=ba r5&name2=value8"
/>

If you have this, it's not XML. Instead of '&' in the url attribute
value, write '&amp;'.

Of course, but the parser I use won't bother on that.
Then this is not a true (compliant) XML parser.
Nov 9 '08 #9
>Unfortunately, I use another engine.
>
Hmm... Did I say that a specific "engine" was necessary for the solution?
Or did you think that FXSL was an "engine"?

It most certainly isn't an "engine".

FXSL is a library of functions/templates, written in pure XSLT. As such, its
functions can be used under any compliant XSLT 2.0 processor or any
compliant XSLT 1.0 processor that either implements the exsl:node-set()
extension function, or is one of the following XSLT 1.0 processors: MSXML
(3,4,6), Xalan, Saxon.

Cheers,
Dimitre Novatchev

"Dimitre Novatchev" <dn********@cnntp.orgwrote in message
news:49***********************@read.cnntp.org...
>
"Ebenezer" <va*********@spam.comwrote in message
news:AA********************@twister1.libero.it...
>Dimitre Novatchev ha scritto:
>>"Ebenezer" <va*********@spam.comwrote in message
news:5j********************@twister1.libero.it.. .
Using FXSL 1.x and its "str-split-to-words" template, such processing is
trivial.

Unfortunately, I use another engine.

Hmm... Did I say that a specific "engine" was necessary for the solution?

FXSL 1.x works with *any* XSLT 1.0 processor that supports the
exsl:node-set() extension function.

There are 3 separate versions for MSXML, Xalan and Saxon, although the
last two XSLT 1.0 processors implement exsl:node-set().

For MSXML, there is a way to implement exslt:node-set() (and in any XSLT
processor that supports extension functions written in inline-JavaScript).
See:

http://www.jenitennison.com/blog/node/24

Lastly, FXSL 2.0 is the latest (since the last 4-5 years) version of FXSL
which is written in and for XSLT 2.0. It doesn't use any extension
functions at all.


Nov 9 '08 #10
Dimitre Novatchev ha scritto:
"Ebenezer" <va*********@spam.comwrote in message
news:4A********************@twister1.libero.it...
>Johannes Koch ha scritto:
>>Ebenezer schrieb:
Let's suppose I have some nodes in an XML file, with an URL attribute:

<node url="mypage.php?name1=value1&foo=bar&foo2=bar2&nam e2=value0" />
<node url="myotherpage.php?name4=value4&foo=bar3&foo2=ba r5&name2=value8"
/>
If you have this, it's not XML. Instead of '&' in the url attribute
value, write '&amp;'.
Of course, but the parser I use won't bother on that.
Then this is not a true (compliant) XML parser.
You got it :)
Nov 10 '08 #11
Dimitre Novatchev ha scritto:
>>Unfortunately, I use another engine.
Hmm... Did I say that a specific "engine" was necessary for the solution?

Or did you think that FXSL was an "engine"?
It most certainly isn't an "engine".
FXSL is a library of functions/templates, written in pure XSLT. As such, its
functions can be used under any compliant XSLT 2.0 processor or any
compliant XSLT 1.0 processor that either implements the exsl:node-set()
extension function, or is one of the following XSLT 1.0 processors: MSXML
(3,4,6), Xalan, Saxon.
Yes, actually I thought that it was an engine, never heard of this library.
Lot of thanks for sharing and helping, Dimitre, I'll dig into that too.
Cheers.
Nov 10 '08 #12

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

5 posts views Thread by inquirydog | last post: by
8 posts views Thread by Paulo Pinto | last post: by
1 post views Thread by Lars Both | last post: by
4 posts views Thread by Moogy | last post: by
10 posts views Thread by Dana B | last post: by
2 posts views Thread by Shannon Mayne | last post: by
reply views Thread by zhoujie | last post: by
1 post views Thread by haryvincent176 | last post: by
reply views Thread by Marylou17 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.