Matching elements that contain different namespaces

H

Hugh Sparks

When processing an xml document that contains elements such as:

<element xmlns="goop"/>
...
<element xmlns="gleep"/>

I want to create two xsl stylesheet templates: one that matches
the elements that contain the namespace declaration for "goop"
and one that matches the elements that contain the namespace
declaration for "gleep".

How should the match patterns be written?

Thanks!

-Hugh Sparks, (e-mail address removed)
 
D

David Carlisle

<xsl:template match="a:element">
....

<xsl:template match="b:element">
....


together with

xmlns:a="goop"
xmlns:b="gleep"

either on those selments, or more typically on the xsl:stylesheet
element, so it is in scope for the whole stylesheet.

Note you have to do this even if you only had one namespace, unprefixed
names in XPathe xpressions and XSLT patterns always refer to no-namespace.

David
 
H

Hugh Sparks

[...How to match elements from different namespaces...]
<xsl:template match="a:element">
...
<xsl:template match="b:element">
...
together with

xmlns:a="goop"
xmlns:b="gleep"

Thank you: That is a very clear answer.
I simplified too much. My problem is a little more bizarre.

I'm not even sure if this is legal xml, but this is what I'm trying to deal
with:

My document contains elements like this:

<document xmlns="MyStuff">
....
<fe:fragment xmlns="goop" xmlns:fe="Fragment" fragment-id="123"/>
....
<fe:fragment xmlns="gleep" xmlns:fe="Fragment" fragment-id="456"/>
....
</document>

The stylesheet root element looks like this:

<xsl:stylesheet version="1.0"
xmlns="http://www.w3.org/1999/xhtml"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fe="Fragment"
I want to write one template that matches the fe:fragment that contains
xmlns="goop" and one template that matches the fe:fragment the contains
the xmlns="gleep".

The fe:fragments are created by a piece of software I don't entirely
control.
It seems to me that the fe:fragment elements have conflicting namepace
membership. Is this legal XML by itself:

<fe:fragment xmlns:fe="Fragment"/>

In other words, can you use a namespace prefix on an element that
contains the prefix definition? I though it could only be used by the
element's children...

I found that my stylesheet didn't work if I didn't define the fe prefix
in the stylesheet root.

And what does this mean:

<root xmlns:fe="Fragment">
<fe:fragment xmlns="goop" xmlns:fe="Fragment"/>
</root>

What is the namespace of fe:fragment?
Is the internal xmlns:fe="Fragment" necessary? Sufficient?
Is this legal xml at all?

In case you're interested in the larger context, the fe:fragments are
created by
by Apache Cocoon's FragmentExtractorTransformer. I have a source document
that I need to extract two different elements for processing by two
different external
Cocoon serializers. When a fragment extractors is configured, you specify
the element name you want to extract and the element's namespace URI.

The intermediate xml document is sent to the stylesheet with the elements
extracted and replaced by the <fe:fragment> elements shown above.
The stylesheet rearranges things a bit and the fragments go back to
the Cocoon pipeline where the original elements get looked up and their
content gets processed.

The only way to distinguish the fragments is by their id attribute and
by the xmlns="blah" they contain. The xmlns="blah" is the namespace
of the extracted element. The fragment does not explicity contain the
name of the element it replaced, which seems like a Bad Thing to me.

I need to handle the fragments differently in the stylesheet depending
on the element they came from. In my case, it happens that each
of the two elements is in a different namespace. So if I can
write the proper template, I can handle the fragments properly.

Thanks,

Hugh Sparks, (e-mail address removed)
 
R

Richard Tobin

I want to write one template that matches the fe:fragment that contains
xmlns="goop" and one template that matches the fe:fragment the contains
the xmlns="gleep".
Why?

Is this legal XML by itself:

<fe:fragment xmlns:fe="Fragment"/>
Yes.

In other words, can you use a namespace prefix on an element that
contains the prefix definition?
Yes.

I found that my stylesheet didn't work if I didn't define the fe prefix
in the stylesheet root.

It should be sufficient to declare it on the elements that use it.
And what does this mean:

<root xmlns:fe="Fragment">
<fe:fragment xmlns="goop" xmlns:fe="Fragment"/>
</root>

What is the namespace of fe:fragment?

"Fragment".

The xmlns="goop" is useless in this example.

-- Richard
 
H

Hugh Sparks

The xmlns="goop" is useless in this example.

Yes, I suspected that.

Just out of curiosity, is the extra xmlns entirely useless?
Wouldn't it apply to the child elements of the fe:fragment?

(I didn't create the fe:fragment elements.
A confounded piece of Cocoon software did that.)

I just want to distinguish the fragments with xslt templates
based on the useless default namespace declarations they
contain. Any ideas?

Thanks,

Hugh Sparks, (e-mail address removed)
 
M

Martin Honnen

Hugh said:
Yes, I suspected that.

Just out of curiosity, is the extra xmlns entirely useless?
Wouldn't it apply to the child elements of the fe:fragment?

It sets a default namespace for the child elements so if there are any
child elements without a prefix in their name then that xmlns="goop"
would indeed apply to them. But you posted
<fe:fragment xmlns="goop" xmlns:fe="Fragment" fragment-id="123"/>
which is an empty element so in that case there are no child elements
and the xmlns="goop" is useless.
 
R

Richard Tobin

Hugh Sparks said:
Just out of curiosity, is the extra xmlns entirely useless?
Wouldn't it apply to the child elements of the fe:fragment?

Yes, the reason I said it was useless was that there were no children
in the example.

-- Richard
 
R

Richard Tobin

Hugh Sparks said:
I just want to distinguish the fragments with xslt templates
based on the useless default namespace declarations they
contain. Any ideas?

The xmlns declarations themselves don't appear in the XPath data model,
so you can't test for them directly.

But the resulting in-scope-namespaces *do* appear in the data model.

This will match any element that has a prefix or the default namespace
bound to "goop":

*[namespace::* = 'goop']

If you insist on it being the default namespace it's a bit trickier:

*[namespace::*[name()=''] = 'goop']

Those will also match descendants of the elements with the
xmlns="goop" declaration, unless they have xmlns= declarations of
their own. If you only want to match the top-level ones, use

*[namespace::* = 'goop'][not(../namespace::* = 'goop')]

-- Richard
 
H

Hugh Sparks

Richard Tobin said:
This will match any element that has a prefix or the default namespace
bound to "goop":

*[namespace::* = 'goop']

[...More profound stuff...]

So to distinguish only my cocoon fragments, the templates would be:

<xsl:template match="fe:fragment[namespace::*='goop']">
...
</xsl:template>


<xsl:template match="fe:fragment[namespace::*='gleep']">
...
</xsl:template>

It works!!

I'm going to ask the author of the FragmentExtractorTransformer about
adding a fragment-name attribute with a value that contains the replaced
element name. That would avoid this obscure difficulty. It's not always
possible for the extracted elements to come from different namespaces.

Thanks very much,

Hugh Sparks, (e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,994
Messages
2,570,222
Members
46,810
Latest member
Kassie0918

Latest Threads

Top