namespace declarations in LibXML

namespace declarations in LibXML

am 15.04.2006 06:48:19 von edward.kawas

Hi,

I am using LibXML to create an xml document. I am also using
namespaces.

The problem that i am running into is that the document that i am
creating has the namespace declaration at each element.

For instance,


blah blah blab
blah blah blab


And I want the following:

blah blah blab
blah blah blab


How can i achieve this?

Thanks.

Ed

Re: namespace declarations in LibXML

am 15.04.2006 19:47:34 von shirsch

edward.kawas@gmail.com wrote:
> Hi,
>
> I am using LibXML to create an xml document. I am also using
> namespaces.
>
> The problem that i am running into is that the document that i am
> creating has the namespace declaration at each element.
>
> For instance,
>
>
> blah blah blab
> blah blah blab
>

>
> And I want the following:
>
> blah blah blab
> blah blah blab
>

>
> How can i achieve this?

Just a WAG, but try something like this on the top element before
writing it out:

my $attr = $dom->createAttributeNS( '', 'dummy', '' );
$dom->getDocumentElement()->setAttributeNodeNS( $attr );

I solved a slightly different namespace-related problem by doing so.

Steve

Re: namespace declarations in LibXML

am 15.04.2006 22:08:46 von edward.kawas

Hi Steve, that didnt help.

Thanks.

Re: namespace declarations in LibXML

am 18.04.2006 20:21:30 von nobull67

edward.kawas@gmail.com wrote:
> Hi,
>
> I am using LibXML to create an xml document. I am also using
> namespaces.
>
> The problem that i am running into is that the document that i am
> creating has the namespace declaration at each element.
>
> For instance,
>
>
> blah blah blab
> blah blah blab
>

>
> And I want the following:
>
> blah blah blab
> blah blah blab
>


Why do you care? The two are semantically identical. Are you concened
about file size or the aesthetic appeal of the XML source?

> How can i achieve this?

I've seen similar problems myself. Perhaps if you posted a _minimal_
but _complete_ stript that manifests the problem[1] I could advise how
to work around it.

[1] This and much other advice can be found in the posting guidelines.

Re: namespace declarations in LibXML

am 20.04.2006 01:51:23 von edward.kawas

Hi,

I realize that they are semantically identical.

Some example code:

use XML::LibXML;
my $root =
XML::LibXML::Element->new( "A" );
$root->setNamespace( "http://www.www.com/foo", "foo" );

my $b =
XML::LibXML::Element->new( "B" );
$b->setNamespace( "http://www.www.com/foo", "foo" );
$b->setAttributeNS( "http://www.www.com/foo", "foo", "name");
$root->appendChild($b);

my $c =
XML::LibXML::Element->new( "C" );
$c->setNamespace( "http://www.www.com/foo", "foo" );
$c->setAttributeNS( "http://www.www.com/foo", "foo", "name");
$root->appendChild($c);

print $root->toString(2);

Thanks.

Ed

Re: namespace declarations in LibXML

am 21.04.2006 19:07:23 von nobull67

edward.kawas@gmail.com wrote:

> Some example code:
>
> use XML::LibXML;
> my $root =
> XML::LibXML::Element->new( "A" );
> $root->setNamespace( "http://www.www.com/foo", "foo" );
>
> my $b =
> XML::LibXML::Element->new( "B" );
> $b->setNamespace( "http://www.www.com/foo", "foo" );
> $b->setAttributeNS( "http://www.www.com/foo", "foo", "name");
> $root->appendChild($b);
>
> my $c =
> XML::LibXML::Element->new( "C" );
> $c->setNamespace( "http://www.www.com/foo", "foo" );
> $c->setAttributeNS( "http://www.www.com/foo", "foo", "name");
> $root->appendChild($c);
>
> print $root->toString(2);

Here you are explicitly re-inroducing the namespace in the child nodes.

The simplest solution is to avoid using setAttributeNS() unless the
node has been attached to the DOM tree already so that it can inherit
namespaces.

The following will only have the namespace in the A node...

my $root = XML::LibXML::Element->new( "A" );
$root->setNamespace( "http://www.www.com/foo", "foo" );

my $b = XML::LibXML::Element->new( "B" );
$root->appendChild($b);
$b->setAttributeNS( "http://www.www.com/foo", "foo", "name");

my $c = XML::LibXML::Element->new( "C" );
$c->setAttribute( "foo:foo", "name");
$root->appendChild($c);

Re: namespace declarations in LibXML

am 24.04.2006 03:09:58 von edward.kawas

Hi Brian,

The code you gave me results in the following:





The B and C elements are not prefixed.

Eddie

Re: namespace declarations in LibXML

am 24.04.2006 13:37:01 von nobull67

edward.kawas@gmail.com wrote:

>
>
>
>

> The B and C elements are not prefixed.

Opps...

my $b = $root->addNewChild("http://www.www.com/foo","B" );
$b->setAttributeNS( "http://www.www.com/foo", "foo", "name");

my $c = XML::LibXML::Element->new( "foo:C" );
$c->setAttribute( "foo:foo", "name");
$root->appendChild($c);

Re: namespace declarations in LibXML

am 24.04.2006 16:41:19 von edward.kawas

Is there any way to not hard code the namespace prefix?

Thanks,

Eddie

Re: namespace declarations in LibXML

am 25.04.2006 18:52:48 von nobull67

edward.kawas@gmail.com wrote:

[ no context given ]

> Is there any way to not hard code the namespace prefix?

I'm sorry I do not understand the question.

Re: namespace declarations in LibXML

am 25.04.2006 22:07:51 von edward.kawas

Hi Brian,

you hard-coded the prefix, i.e. $c->setAttribute("foo:foo", "name");
can we avoid this somehow? I did avoid it, by appending a $root->prefix
to the attribute foo.

So even if my solution to the above was correct, if I have 2 elements
and I want one of the elements to import/adopt/add the other, the
namespace declaration will appear twice, i.e.

Element 1:





Element 2:






And if element 1 imports or adds, etc, element 2, the result is:










I cant believe that there isnt a way to do this properly without
hardcoding prefixes, removing declarations, etc.

I did notice that if I use $root->addTextElement("blah blah"); and
$root has the namespaces declared, the node added is prefixed properly.
I tried looking for the source that does this to give me ideas, but I
couldnt find it. Do you have any suggestions?

Thanks Brian for your continued attempts at resolving my problem. I
appreciate it.

Eddie

Re: namespace declarations in LibXML

am 25.04.2006 22:11:43 von edward.kawas

sorry,
$root->addTextElement("blah blah");
should read:
$root->appendTextChild("D", "blah");

Re: namespace declarations in LibXML

am 26.04.2006 13:48:35 von nobull67

edward.kawas@gmail.com wrote:

[ No relevant context given. Please try to follow accepted conventions.
]

> you hard-coded the prefix, i.e. $c->setAttribute("foo:foo", "name");
> can we avoid this somehow?

I did avoid it in the alternative method I showed you about three lines
earlier.

How does that not meet your requirements?

I have observed over the years that there is a very high correlation
between people who follow-up without including relevant conext and
people who ask questions that are (or at least appear to be) answered
in the post to which they are replying.

Re: namespace declarations in LibXML

am 26.04.2006 15:48:12 von edward.kawas

Sorry, given the following, I looked at how $c was created:

my $b = $root->addNewChild("http://www.www.com/foo","B" );
$b->setAttributeNS( "http://www.www.com/foo", "foo", "name");

my $c = XML::LibXML::Element->new( "foo:C" );
$c->setAttribute( "foo:foo", "name");
$root->appendChild($c);

So it does indeed do what I wished. One last question. Given the
following code:
use XML::LibXML;


my $root = XML::LibXML::Element->new( "A" );
$root->setNamespace( "http://www.www.com/foo", "foo" );

my $b = $root->addNewChild("http://www.www.com/foo","B" );
$b->setAttributeNS( "http://www.www.com/foo", "att", "name");

my $c = $root->addNewChild("http://www.www.com/foo","C" );
$c->setAttributeNS( "http://www.www.com/foo", "art", "name");
print $root->toString(2);

my $root2 = XML::LibXML::Element->new( "E" );
$root2->setNamespace( "http://www.www.com/foo", "foo" );

my $F = $root2->addNewChild("http://www.www.com/foo","F" );
$F->setAttributeNS( "http://www.www.com/foo", "attf", "name");

my $g = $root2->addNewChild("http://www.www.com/foo","G" );
$g->setAttributeNS( "http://www.www.com/foo", "artg", "name");

print $root2->toString(2);

How can $root add $root2 such that the output is









I have tried $root->appendChild($root2), $root->addChild($root2), etc.

Thanks again. You have helped a lot.

Ed

Re: namespace declarations in LibXML

am 30.04.2006 17:58:06 von nobull67

edward.kawas@gmail.com wrote:
> Given the following code:
> use XML::LibXML;
>
> my $root = XML::LibXML::Element->new( "A" );
> $root->setNamespace( "http://www.www.com/foo", "foo" );
>
> my $b = $root->addNewChild("http://www.www.com/foo","B" );
> $b->setAttributeNS( "http://www.www.com/foo", "att", "name");
>
> my $c = $root->addNewChild("http://www.www.com/foo","C" );
> $c->setAttributeNS( "http://www.www.com/foo", "art", "name");
> print $root->toString(2);
>
> my $root2 = XML::LibXML::Element->new( "E" );
> $root2->setNamespace( "http://www.www.com/foo", "foo" );
>
> my $F = $root2->addNewChild("http://www.www.com/foo","F" );
> $F->setAttributeNS( "http://www.www.com/foo", "attf", "name");
>
> my $g = $root2->addNewChild("http://www.www.com/foo","G" );
> $g->setAttributeNS( "http://www.www.com/foo", "artg", "name");
>
> print $root2->toString(2);
>
> How can $root add $root2 such that the output is
>
>
>
>
>
>
>

>

>
> I have tried $root->appendChild($root2), $root->addChild($root2), etc.

This is something that's bugged me a lot in the past. I've manged to
work arround it to date most of the time using the approaches already
mentioned in this thread.

The rest of the time I've just put up with is. It's only cosmetic after
all.

I've always thought that XML::LibXML should have a function to strip
redundant xmlns declarations from a tree.

I've tried...

sub remove_redundant_namespace {
my $node = shift;
my $parent = $node->parentNode;
for my $ns ( $node->getNamespaces ) {
no warnings 'uninitialized';
if ($ns->name eq $parent->lookupNamespacePrefix($ns->value)) {
$node->removeChild($ns);
}
}
remove_redundant_namespace($_) for $node->childNodes;
}

....but this doesn't seem to work because
XML::LibXML::Node::removeChild() does not seem to recognise the
XML::LibXML::Namespace object as a child.

Re: namespace declarations in LibXML

am 01.05.2006 16:16:37 von edward.kawas

Hi Brian,

I tried the following to remove the extra namespace declarations and it
did work (may not be too efficient though):

# code from above posts to create 2 separate elements and then merge
# them so that the final result is an element with 2 namespace
declarations
# that are the same

my $parser = XML::LibXML::->new();
$parser->clean_namespaces(1);
my $doc = $parser->parse_string($root->toString(2));
print $doc->toString();


Eddie

Brian McCauley wrote:
> edward.kawas@gmail.com wrote:
> > Given the following code:
> > use XML::LibXML;
> >
> > my $root = XML::LibXML::Element->new( "A" );
> > $root->setNamespace( "http://www.www.com/foo", "foo" );
> >
> > my $b = $root->addNewChild("http://www.www.com/foo","B" );
> > $b->setAttributeNS( "http://www.www.com/foo", "att", "name");
> >
> > my $c = $root->addNewChild("http://www.www.com/foo","C" );
> > $c->setAttributeNS( "http://www.www.com/foo", "art", "name");
> > print $root->toString(2);
> >
> > my $root2 = XML::LibXML::Element->new( "E" );
> > $root2->setNamespace( "http://www.www.com/foo", "foo" );
> >
> > my $F = $root2->addNewChild("http://www.www.com/foo","F" );
> > $F->setAttributeNS( "http://www.www.com/foo", "attf", "name");
> >
> > my $g = $root2->addNewChild("http://www.www.com/foo","G" );
> > $g->setAttributeNS( "http://www.www.com/foo", "artg", "name");
> >
> > print $root2->toString(2);
> >
> > How can $root add $root2 such that the output is
> >
> >
> >
> >
> >
> >
> >

> >

> >
> > I have tried $root->appendChild($root2), $root->addChild($root2), etc.
>
> This is something that's bugged me a lot in the past. I've manged to
> work arround it to date most of the time using the approaches already
> mentioned in this thread.
>
> The rest of the time I've just put up with is. It's only cosmetic after
> all.
>
> I've always thought that XML::LibXML should have a function to strip
> redundant xmlns declarations from a tree.
>
> I've tried...
>
> sub remove_redundant_namespace {
> my $node = shift;
> my $parent = $node->parentNode;
> for my $ns ( $node->getNamespaces ) {
> no warnings 'uninitialized';
> if ($ns->name eq $parent->lookupNamespacePrefix($ns->value)) {
> $node->removeChild($ns);
> }
> }
> remove_redundant_namespace($_) for $node->childNodes;
> }
>
> ...but this doesn't seem to work because
> XML::LibXML::Node::removeChild() does not seem to recognise the
> XML::LibXML::Namespace object as a child.