Don't crosspost to two irrelevant lists, please

Derick

On Sun, 14 Mar 2004, Vivian Steller wrote:

> hello,
>
> once again a post about the tricky namespaces. I played with the following
> functions concerning namespaces:
>
> domdocument->createElementNS
> domdocument->createAttributeNS
> domelement->setAttributeNS
> domelement->getAttributeNS
> (domelement->hasAttributeNS)
>
> as i found out the behavior of some functions differs when handling
> namespaces. maybe we can start a thread thinking about this behavior - at
> the moment i don't have the "enlightened" view into this very complex
> theme. would be nice if you could help me/us understanding namespaces a bit
> more...
>
> ok here are the things i found out. copy the code to your editor and step
> through the examples - the important output is given in the comments.
> Thanks for taking time to that :)
>
> /*############################ START ############################*/
> <pre>
>
> /* SIMPLE NAMESPACE EXAMPLE */
> <?php
>         $doc = new DomDocument();
>         $xpath = new DomXPath($doc);
>
>         /* SIMPLE NAMESPACE EXAMPLE */
>         $node1 = $doc->createElementNS("namespaceURI", "nodeName");
>         $node1 = $doc->appendChild($node1);
>
>         print(htmlspecialchars("\n" . $doc->saveXML() . "\n"));
>         // Output
>         // > <nodeName xmlns="namespaceURI"/>
>
>         $namespaces = $xpath->query("//namespace::*");
>         foreach($namespaces as $item) {
>                 print($item->nodeName . " = " . $item->nodeValue . "\n");
>         }
>         // Output
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace
>         // > xmlns = namespaceURI
>         $doc->removeChild($node1);
> ?>
>
> Right behavior so far!
>
>
>
> /* NAMESPACE WITH PREFIX EXAMPLE */
> <?php
>         /* NAMESPACE WITH PREFIX EXAMPLE */
>         $node2 = $doc->createElementNS("namespaceURI", "prefix:localName");
>         $node2 = $doc->appendChild($node2);
>
>         print(htmlspecialchars("\n" . $doc->saveXML() . "\n"));
>         // Output
>         // > <prefix:localName xmlns:prefix="namespaceURI"/>
>
>         $namespaces = $xpath->query("//namespace::*");
>         foreach($namespaces as $item) {
>                 print($item->nodeName . " = " . $item->nodeValue . "\n");
>         }
>         // Output
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace
>         // > xmlns:prefix = namespaceURI
>
>         // $doc->removeChild($node2);
> ?>
>
> Still right behavior!
>
>
>
> /* NAMESPACE WITH EXISTING PREFIX EXAMPLE */
> <?php
>         /* NAMESPACE WITH EXISTING PREFIX EXAMPLE */
>         $node3 = $doc->createElementNS("namespaceURI", "localName");
>         $node3 = $node2->appendChild($node3);
>
>         print(htmlspecialchars("\n" . $doc->saveXML() . "\n"));
>         // Output
>         // > <prefix:localName xmlns:prefix="namespaceURI"> ¬
>         //              <prefix:localName/> ¬
>         //       </prefix:localName>
>
>         $namespaces = $xpath->query("//namespace::*");
>         foreach($namespaces as $item) {
>                 print($item->nodeName . " = " . $item->nodeValue . "\n");
>         }
>         // Output
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace   (node2)
>         // > xmlns:prefix = namespaceURI                                             
>    (node2)
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace   (node3)
>         // > xmlns:prefix = namespaceURI                                             
>    (node3)
>
>         // $doc->removeChild($node3);
> ?>
>
> Right behavior, but namespace node will be removed, xpath-expression shows
> prefix - thats still right.
>
>
>
> /* IMPORT NAMESPACE NODE WITHOUT CHILDREN EXAMPLE */
> <?php
>         /* IMPORT NAMESPACE NODE WITHOUT CHILDREN EXAMPLE */
>         $newDoc = new DomDocument();
>         $newXpath = new DomXPath($newDoc);
>
>         $newNode3 = $newDoc->importNode($node3);        // second argument $deep = 
> FALSE!!
>         $newNode3 = $newDoc->appendChild($newNode3);
>
>         print(htmlspecialchars("\n" . $newDoc->saveXML() . "\n"));
>         // Output
>         // > <localName/>
>
>         $newNamespaces = $newXpath->query("//namespace::*");
>         foreach($newNamespaces as $item) {
>                 print($item->nodeName . " = " . $item->nodeValue . "\n");
>         }
>         // Output
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace   (newNode3)
>
>         $newDoc->removeChild($newNode3);
> ?>
>
> Maybe right behavior, but i think loosing the namespace while importing the
> node without its children is a bit dangerous...
>
>
>
> /* IMPORT NAMESPACE NODE EXAMPLE */
> <?php
>         /* IMPORT NAMESPACE NODE EXAMPLE */
>         $newNode3 = $newDoc->importNode($node3, TRUE);  // second argument $deep =
> TRUE now!!
>         $newNode3 = $newDoc->appendChild($newNode3);
>
>         print(htmlspecialchars("\n" . $newDoc->saveXML() . "\n"));
>         // Output
>         // > <prefix:localName xmlns:prefix="namespaceURI"/>
>
>         $newNamespaces = $newXpath->query("//namespace::*");
>         foreach($newNamespaces as $item) {
>                 print($item->nodeName . " = " . $item->nodeValue . "\n");
>         }
>         // Output
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace   (newNode3)
>         // > xmlns:prefix = namespaceURI                                             
>    (newNode3)
>
>         $newDoc->removeChild($newNode3);
> ?>
>
> Now the namespace node will be imported as well, but it is not possible
> to import the "namespaced" node without its children...
>
>
>
> /* SET A NAMESPACE ATTRIBUTE WITHOUT PREFIX AND UNDEFINED NAMESPACE */
> <?php
>         /* SET A NAMESPACE ATTRIBUTE WITHOUT PREFIX AND UNDEFINED NAMESPACE */
>         //$node3->setAttributeNS("attrNamespaceURI", "attrName", "attrValue");
>         // Output
>         // > Fatal error:  Uncaught exception 'domexception' with message
> 'Namespace Error'
> ?>
>
> Error message is acceptable because attribute nodes could not have their own
> "xmlns" attributes! They have to be defined with a prefix (if their is no
> prefix defined for this namespace!)... Therefor the folling example should
> not occur an error...
>
> <?php
>         /* SET A NAMESPACE ATTRIBUTE WITH EXISTING NAMESPACE */
>         //$node3->setAttributeNS("namespaceURI", "attrName", "attrValue");
>         // Output would be
>         // > <prefix:localName xmlns:prefix="namespaceURI">
>         //              <prefix:localName prefix:attrName="attrValue"/>
>         //       </prefix:localName>
> ?>
>
> And it doesn't. Right! The import of this node will be done correctly!
>
>
>
> /* SET A NAMESPACE ATTRIBUTE WITH PREFIX AND UNDEFINED NAMESPACE EXAMPLE */
> <?php
>         $node3->setAttributeNS("attrNamespaceURI", "prefix:attrName", "attrValue");
>
>         print(htmlspecialchars("\n" . $doc->saveXML() . "\n"));
>         // Output
>         // > <prefix:localName xmlns:prefix="namespaceURI"> ¬
>         //              <prefix:localName xmlns:prefix="attrNamespaceURI"
> prefix:attrName="attrValue"/> ¬
>         //       </prefix:localName>
>
>         $namespaces = $xpath->query("//namespace::*");
>         foreach($namespaces as $item) {
>                 print($item->nodeName . " = " . $item->nodeValue . "\n");
>         }
>         // Output
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace   (node2)
>         // > xmlns:prefix = namespaceURI                                             
>    (node2)
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace   (node3)
>         // > xmlns:prefix = attrNamespaceURI                                    
> (node3)
>
>         // $doc->removeChild($node3);
>         print("Node3 namespace: " . $node3->namespaceURI . "\n");
>         // Output
>         // > Node3 namespace: namespaceURI
> ?>
>
> Seems confusing but namespace of node is still "namespaceURI"
> And it will result in a conflict in the following example...
>
>
>
> /* IMPORT NAMESPACE NODE WITH NAMESPACE-PREFIX DEFINITION EXAMPLE */
> <?php
>         /* IMPORT NAMESPACE NODE EXAMPLE */
>         $newNode3 = $newDoc->importNode($node3, TRUE);  // second argument $deep =
> TRUE now!!
>         $newNode3 = $newDoc->appendChild($newNode3);
>
>         print(htmlspecialchars("\n" . $newDoc->saveXML() . "\n"));
>         // Output
>         // > <prefix:localName xmlns:prefix="attrNamespaceURI"
> prefix:attrName="attrValue"/>
>
>         $newNamespaces = $newXpath->query("//namespace::*");
>         foreach($newNamespaces as $item) {
>                 print($item->nodeName . " = " . $item->nodeValue . "\n");
>         }
>         // Output
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace   (newNode3)
>         // > xmlns:prefix = namespaceURI                                             
>    (newNode3)
>         print("NewNode3 namespace: " . $newNode3->namespaceURI . "\n");
>         // Output
>         // > NewNode3 namespace: attrNamespaceURI
>
>         $newDoc->removeChild($newNode3);
>         $node2->removeChild($node3);
> ?>
>
> WOW!! NamespaceURI has been changed while importing node - i think
> that this behavior isn't right yet. NamespaceURI shouldn't depend on
> xmlns:prefix attribute - instead it simply should loose its prefix and
> set its "xmlns" attribute to its current namespaceURI!
>
>
>
> /* SET A NAMESPACE ATTRIBUTE WITH NEW ATTRIBUTE NODE EXAMPLE */
> I'm now changing to node2 -  getting to complicated
> <?php
>         //$attr2 = $doc->createAttributeNS("attrNamespaceURI", "prefix:attrName");
>         // Output
>         // > Fatal error:  Uncaught exception 'domexception' with message
> 'Namespace Error'
> ?>
>
> It seems that the behavior handling namespaces isn't the same in
> DomDocument::createAttributeNS() and DomElement::setAttributeNS(), as you
> can see in the
> SET A NAMESPACE ATTRIBUTE WITH PREFIX AND UNDEFINED NAMESPACE EXAMPLE
>
> But using a new namespace-prefix it will work correctly.
> <?php
>         $attr2 = $doc->createAttributeNS("attrNamespaceURI", "newPrefix:attrName");
>         // Output:
>         // > <prefix:localName xmlns:prefix="namespaceURI"
> xmlns:newPrefix="attrNamespaceURI"/>
> ?>
>
> Note: the "xmlns:newPrefix" declaration will be appended to the root
> node of the document on creation of this NS attribute. This could
> result in trouble while cloning/importing/deleting a node holding an
> "newPrefix"ed attribute!?
>
> <?php
>         $node3 = $doc->createElementNS("namespaceURI", "nodeName");
>         $node3 = $node2->appendChild($node3);
>         $node3->appendChild($attr2);
>
>         print(htmlspecialchars("\n" . $doc->saveXML() . "\n"));
>         // Output
>         // > <prefix:localName xmlns:prefix="namespaceURI"
> xmlns:newPrefix="attrNamespaceURI">
>         //              <prefix:nodeName newPrefix:attrName=""/>
>         //       </prefix:localName>
>
>         $namespaces = $xpath->query("//namespace::*");
>         foreach($namespaces as $item) {
>                 print($item->nodeName . " = " . $item->nodeValue . "\n");
>         }
>         // Output
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace   (node2)
>         // > xmlns:newprefix = attrNamespaceURI                                 
> (node2)
>         // > xmlns:prefix = namespaceURI                                             
>    (node2)
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace   (node3)
>         // > xmlns:newprefix = attrNamespaceURI                                 
> (node3)
>         // > xmlns:prefix = namespaceURI                                             
>    (node3)
>         $node2->removeChild($node3);
>         // Output
>         // > <prefix:localName xmlns:prefix="namespaceURI"
> xmlns:newPrefix="attrNamespaceURI"/>
> ?>
> As you can see the "xmlns:newPrefix" attribute is still appended to the root
> node of the document. Because of the lack of a (reasonable) possibility to
> remove an "xmlns" declaration the reset of an attribute using this prefix
> will result in an error:
>
> <?php
>         // $attr2 = $doc->createAttributeNS("newAttrNamespaceURI",
> "newPrefix:attrName");
>         // Output
>         // > Fatal error:  Uncaught exception 'domexception' with message
> 'Namespace Error'
> ?>
>
> I think it would be easier to append the "xmlns" declarations on those nodes
> which have an attribute/child of this namespace.
>
>
>
> /* SET AN XMLNS NAMESPACE ATTRIBUTE EXAMPLE */
> As I said before there is no (reasonable) possiblity to remove an "xmlns"
> declaration (you could do this by cloning nodes in the hope for a bug in the
> source leading to the loss of this declaration... very uncomforable:).
>
> But there is a possibility to check if a xmlns is defined using xpath (I use
> this xpath in this document all the time).
>
> I found out that you also can set an "xmlns" declaration using the right
> namespaces (which you can find in the sources of libxml and ext/dom).
> Have a look:
>
> <?php
>         // xmlns Namespace: "http://www.w3.org/2000/xmlns/";
>         // xml Namespace: "http://www.w3.org/XML/1998/namespace";
>         $node2->setAttributeNS("http://www.w3.org/2000/xmlns/";,
> "xmlns:anotherNewPrefix", "anotherNewNamespace");
>
>         print(htmlspecialchars("\n" . $doc->saveXML() . "\n"));
>         // Output
>         // > <prefix:localName xmlns:prefix="namespaceURI"
> xmlns:newPrefix="attrNamespaceURI"
> xmlns:anotherNewPrefix="anotherNewNamespace"/>
>
>         $namespaces = $xpath->query("//namespace::*");
>         foreach($namespaces as $item) {
>                 print($item->nodeName . " = " . $item->nodeValue . "\n");
>         }
>         // Output
>         // > xmlns:xml = http://www.w3.org/XML/1998/namespace   (node2)
>         // > xmlns:anotherNewPrefix = anotherNewNamespace               (node2)
>         // > xmlns:newprefix = attrNamespaceURI                                 
> (node2)
>         // > xmlns:prefix = namespaceURI                                             
>    (node2)
> ?>
>
> This is very fine but the behavior (in this case) isn't very logic: setting
> an elements'/attributes' namespace the intepreter checks whether a prefix is
> defined for this namespace or not. Though the following expression should
> not
> result in an error while a prefix for the used namespace is defined already:
>
> <?php
>         $node2->setAttributeNS("http://www.w3.org/2000/xmlns/";,
> "justAnotherNewPrefix", "justAnotherNewNamespace");
>         // Output:
>         // > Fatal error:  Uncaught exception 'domexception' with message
> 'Namespace Error'
> ?>
>
> But unforunately it does! You could solve this problem by simply setting the
> "http://www.w3.org/2000/xmlns/"; namespace as a default namespace like
> "http://www.w3.org/XML/1998/namespace";. Then the behavior would be more
> consequent...
>
> </pre>
>
> /*############################ END ############################*/
>
> Ok I think this is enough about namespaces for today. I hope i could help
> someone understanding namespaces and the problems with it.
>
> Any comments would be appreciated.
>
> Thanks in advance.
>
> vivi
>
>

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to