gnash-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Gnash-commit] /srv/bzr/gnash/trunk r10316: Corrections and new implemen


From: Benjamin Wolsey
Subject: [Gnash-commit] /srv/bzr/gnash/trunk r10316: Corrections and new implementations of XMLNode methods and XML parsing.
Date: Fri, 21 Nov 2008 13:03:31 +0100
User-agent: Bazaar (1.5)

------------------------------------------------------------
revno: 10316
committer: Benjamin Wolsey <address@hidden>
branch nick: trunk
timestamp: Fri 2008-11-21 13:03:31 +0100
message:
  Corrections and new implementations of XMLNode methods and XML parsing.
modified:
  libcore/asobj/XMLNode_as.cpp
  libcore/asobj/XMLNode_as.h
  libcore/asobj/XML_as.cpp
  libcore/asobj/XML_as.h
  testsuite/actionscript.all/XMLNode.as
    ------------------------------------------------------------
    revno: 10315.1.1
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Fri 2008-11-21 09:11:07 +0100
    message:
      Allow setting XMLNode attributes.
    modified:
      libcore/asobj/XMLNode_as.cpp
      libcore/asobj/XMLNode_as.h
      libcore/asobj/XML_as.cpp
    ------------------------------------------------------------
    revno: 10315.1.2
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Fri 2008-11-21 09:14:38 +0100
    message:
      Test passes.
    modified:
      testsuite/actionscript.all/XMLNode.as
    ------------------------------------------------------------
    revno: 10315.1.3
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Fri 2008-11-21 09:26:05 +0100
    message:
      Test enumeration order of attributes (it's normal, but different from
      order when parsing, which suggests that parsing constructs values in 
      a different order).
    modified:
      libcore/asobj/XMLNode_as.cpp
      testsuite/actionscript.all/XMLNode.as
    ------------------------------------------------------------
    revno: 10315.1.4
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Fri 2008-11-21 10:51:27 +0100
    message:
      Correct attribute construction order during parsing. Implement
      XMLNode.getNamespaceForPrefix.
    modified:
      libcore/asobj/XMLNode_as.cpp
      libcore/asobj/XMLNode_as.h
      libcore/asobj/XML_as.cpp
      libcore/asobj/XML_as.h
      testsuite/actionscript.all/XMLNode.as
    ------------------------------------------------------------
    revno: 10315.1.5
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Fri 2008-11-21 11:50:16 +0100
    message:
      Implement XMLNode.getPrefixForNamespace.
    modified:
      libcore/asobj/XMLNode_as.cpp
      libcore/asobj/XMLNode_as.h
      testsuite/actionscript.all/XMLNode.as
    ------------------------------------------------------------
    revno: 10315.1.6
    committer: Benjamin Wolsey <address@hidden>
    branch nick: test
    timestamp: Fri 2008-11-21 12:10:23 +0100
    message:
      Add some more tests and a minor correction to attributes parsing.
    modified:
      libcore/asobj/XML_as.cpp
      testsuite/actionscript.all/XMLNode.as
=== modified file 'libcore/asobj/XMLNode_as.cpp'
--- a/libcore/asobj/XMLNode_as.cpp      2008-11-20 17:50:40 +0000
+++ b/libcore/asobj/XMLNode_as.cpp      2008-11-21 10:50:16 +0000
@@ -27,7 +27,9 @@
 #include "Object.h" // for getObjectInterface
 #include "VM.h" // for getting the string_table.
 #include "string_table.h" 
+#include "PropertyList.h"
 
+#include <boost/bind.hpp>
 #include <string>
 #include <sstream>
 #include <vector>
@@ -37,6 +39,16 @@
 
 namespace gnash {
 
+namespace {
+    void enumerateAttributes(const XMLNode_as& node,
+            PropertyList::SortedPropertyList&attributes);
+    bool prefixMatches(const PropertyList::SortedPropertyList::value_type& val,
+            const std::string& prefix);
+    bool namespaceMatches(
+            const PropertyList::SortedPropertyList::value_type& val,
+            const std::string& ns);
+}
+
 static as_value xmlnode_new(const fn_call& fn);
 static as_value xmlnode_nodename(const fn_call& fn);
 static as_value xmlnode_node_value(const fn_call& fn);
@@ -67,6 +79,7 @@
     :
     as_object(getXMLNodeInterface()),
     _parent(0),
+    _attributes(new as_object),
     _type(Element)
 {
     //log_debug("%s: %p", __PRETTY_FUNCTION__, this);
@@ -79,6 +92,7 @@
     :
     as_object(getXMLNodeInterface()),
     _parent(0), // _parent is never implicitly copied
+    _attributes(0),
     _name(tpl._name),
     _value(tpl._value),
     _type(tpl._type)
@@ -243,7 +257,8 @@
 
     XMLNode_as *previous_node = NULL;
     Children::reverse_iterator itx;
-    for (itx = _parent->_children.rbegin(); itx != _parent->_children.rend(); 
itx++)
+    for (itx = _parent->_children.rbegin(); itx != _parent->_children.rend();
+            itx++)
     {
         if (itx->get() == this)
         {
@@ -261,6 +276,77 @@
     stringify(*this, xmlout, encode);
 }
 
+void
+XMLNode_as::setAttribute(const std::string& name, const std::string& value)
+{
+    if (_attributes) {
+        string_table& st = _vm.getStringTable();
+        _attributes->set_member(st.find(name), value);
+    }
+}
+
+bool
+XMLNode_as::getPrefixForNamespace(const std::string& ns, std::string& prefix)
+{
+    XMLNode_as* node = this;
+    PropertyList::SortedPropertyList::const_iterator it; 
+    
+    while (node)
+    {
+        PropertyList::SortedPropertyList attrs;
+        enumerateAttributes(*node, attrs);
+        if (!attrs.empty())
+        {
+            it = std::find_if(attrs.begin(), attrs.end(), 
+                        boost::bind(namespaceMatches, _1, ns));
+            if (it != attrs.end()) break;
+        }
+        node = node->getParent();
+    }
+
+    // None found.
+    if (!node) return false;
+
+    // Return the matching prefix
+    const std::string& name = it->first;
+    std::string::size_type pos = name.find(':');
+
+    /// If we have a match and there is no colon, this is a standard
+    /// namespace.
+    if (pos == std::string::npos) return true;
+    
+    prefix = name.substr(pos + 1);
+    return true;
+    
+}
+
+void
+XMLNode_as::getNamespaceForPrefix(const std::string& prefix, std::string& ns)
+{
+    XMLNode_as* node = this;
+    PropertyList::SortedPropertyList::const_iterator it; 
+    
+    while (node)
+    {
+        PropertyList::SortedPropertyList attrs;
+        enumerateAttributes(*node, attrs);
+        if (!attrs.empty())
+        {
+            it = std::find_if(attrs.begin(), attrs.end(), 
+                        boost::bind(prefixMatches, _1, prefix));
+            if (it != attrs.end()) break;
+        }
+        node = node->getParent();
+    }
+
+    // None found; return undefined
+    if (!node) return;
+
+    // Return the matching namespace
+    ns = it->second;
+
+}
+
 /* static private */
 void
 XMLNode_as::stringify(const XMLNode_as& xml, std::ostream& xmlout, bool 
encode) 
@@ -278,16 +364,20 @@
 #endif
 
     // Create the beginning of the tag
-    if ( nodename.size() )
+    if (!nodename.empty())
     {
         xmlout << "<" << nodename;
     
         // Process the attributes, if any
-        Attributes::const_iterator ita;
-        for (ita = xml._attributes.begin(); ita != xml._attributes.end(); 
ita++)
-        {
-            const XMLAttr& xa = *ita;
-            xmlout << " " << xa.name() << "=\"" << xa.value() << "\"";
+        PropertyList::SortedPropertyList attrs;
+        enumerateAttributes(xml, attrs);
+        if (!attrs.empty()) {
+
+            for (PropertyList::SortedPropertyList::const_iterator i = 
+                    attrs.begin(), e = attrs.end(); i != e; ++i) { 
+
+                xmlout << " " << i->first << "=\"" << i->second << "\"";
+            }
         }
 
        // If the node has no content, just close the tag now
@@ -499,8 +589,15 @@
 xmlnode_getNamespaceForPrefix(const fn_call& fn)
 {
     boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    log_unimpl("XMLNode.getNamespaceForPrefix");
-    return as_value();
+    if (!fn.nargs) {
+        return as_value();
+    }
+
+    std::string ns;
+
+    ptr->getNamespaceForPrefix(fn.arg(0).to_string(), ns);
+    if (ns.empty()) return as_value();
+    return as_value(ns);
 }
 
 
@@ -508,8 +605,18 @@
 xmlnode_getPrefixForNamespace(const fn_call& fn)
 {
     boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
-    log_unimpl("XMLNode.getPrefixForNamespace");
-    return as_value();
+    if (!fn.nargs) {
+        return as_value();
+    }
+
+    std::string prefix;
+
+    // Return undefined if none found; otherwise the prefix string found.
+    // This can be empty if it is a standard namespace.
+    if (!ptr->getPrefixForNamespace(fn.arg(0).to_string(), prefix)) {
+        return as_value();
+    }
+    return as_value(prefix);
 }
 
 
@@ -640,10 +747,8 @@
     as_value rv;
     rv.set_null();
     
-    //log_debug("xmlnode_node_value called with %d args against 'this' = %p", 
fn.nargs, ptr);
     if ( fn.nargs == 0 )
     {
-           //log_debug("  nodeValue() returns '%s'", ptr->nodeValue().c_str());
         const std::string& val = ptr->nodeValue();
         if ( ! val.empty() ) rv = val;
     }
@@ -683,29 +788,11 @@
 as_value
 xmlnode_attributes(const fn_call& fn)
 {
-    
     boost::intrusive_ptr<XMLNode_as> ptr = ensureType<XMLNode_as>(fn.this_ptr);
 
-    VM& vm = ptr->getVM();
-    string_table& st = vm.getStringTable();
-
-    XMLNode_as::Attributes& attrs = ptr->attributes();
-
-    // Attributes are simple objects.
-    boost::intrusive_ptr<as_object> ret = new as_object(); 
-
-    for (XMLNode_as::Attributes::const_iterator it=attrs.begin(),
-        itEnd=attrs.end(); it != itEnd; ++it)
-    {
-
-        const XMLAttr& at = *it;
-        const std::string& name = at.name();
-        const std::string& val = at.value();
-        // These must be enumerable !
-        ret->set_member(st.find(name), val);
-    }
-
-    return as_value(ret); 
+    as_object* attrs = ptr->getAttributes();
+    if (attrs) return as_value(attrs);
+    return as_value(); 
 }
 
 /// Read-only property; evaluates the specified XML object and
@@ -841,10 +928,66 @@
        // Mark parent
        if ( _parent ) _parent->setReachable();
 
+       // Mark attributes object
+       if (_attributes) _attributes->setReachable();
+
        markAsObjectReachable();
 }
 #endif // GNASH_USE_GC
 
+namespace {
+
+void
+enumerateAttributes(const XMLNode_as& node,
+            PropertyList::SortedPropertyList& attrs)
+{
+    attrs.clear();
+    const as_object* obj = node.getAttributes();
+    if (obj) {
+        obj->enumerateProperties(attrs);
+    }
+
+}
+
+/// Return true if this attribute is a namespace specifier and the
+/// namespace matches.
+bool
+namespaceMatches(const PropertyList::SortedPropertyList::value_type& val,
+        const std::string& ns)
+{
+    StringNoCaseEqual noCaseCompare;
+    return (noCaseCompare(val.first.substr(0,5), "xmlns") && 
+                noCaseCompare(val.second, ns));
+}
+
+
+bool
+prefixMatches(const PropertyList::SortedPropertyList::value_type& val,
+        const std::string& prefix)
+{
+    const std::string& name = val.first;
+    StringNoCaseEqual noCaseCompare;
+
+    // An empty prefix searches for a standard namespace specifier.
+    // Attributes are stored with no trailing or leading whitespace,
+    // so a simple comparison should do. TODO: what about "xmlns:"?
+    if (prefix.empty()) {
+        return noCaseCompare(name, "xmlns");
+    }
+
+    if (!noCaseCompare(name.substr(0, 5), "xmlns")) return false;
+
+    std::string::size_type pos = name.find(':');
+
+    // There is no colon or nothing after the colon, so this node has
+    // no matching prefix.
+    if (pos == std::string::npos) return false;
+
+    return noCaseCompare(prefix, name.substr(pos + 1));
+}
+
+} // anonymous namespace
+
 } // end of gnash namespace
 
 // Local Variables:

=== modified file 'libcore/asobj/XMLNode_as.h'
--- a/libcore/asobj/XMLNode_as.h        2008-11-19 08:41:47 +0000
+++ b/libcore/asobj/XMLNode_as.h        2008-11-21 10:50:16 +0000
@@ -97,8 +97,7 @@
     NodeType nodeType() const { return _type; }
 
     /// Set the type of an XML Node.
-    void nodeTypeSet(NodeType type)
-    {
+    void nodeTypeSet(NodeType type) {
            _type = type;
     }
 
@@ -111,6 +110,14 @@
     /// Set value of this node, overriding any previous value
     void nodeValueSet(const std::string& value) { _value = value; }
 
+    /// Performs a recursive search of node attributes to find a match
+    void getNamespaceForPrefix(const std::string& prefix, std::string& ns);
+
+    /// Performs a recursive search of node attributes to find a match
+    //
+    /// @return false if no match found.
+    bool getPrefixForNamespace(const std::string& ns, std::string& prefix);
+
     void setNamespaceURI(const std::string value) {
         _namespaceURI = value;
     }
@@ -129,12 +136,8 @@
     // Use a list for quick erasing
     typedef std::list< boost::intrusive_ptr<XMLNode_as> > Children;
 
-    typedef std::vector< XMLAttr > Attributes;
-
     Children& childNodes() { return _children; }
 
-    Attributes& attributes() { return _attributes; }
-    
     XMLNode_as& operator = (XMLNode_as &node) {
         log_debug("%s: \n", __PRETTY_FUNCTION__);
         if (this == &node) return *this;
@@ -160,7 +163,6 @@
     /// name, value, and attributes as the specified XML object. If deep
     /// is set to true, all child nodes are recursively cloned, resulting
     /// in an exact copy of the original object's document tree. 
-    ///
     boost::intrusive_ptr<XMLNode_as> cloneNode(bool deep);
 
     /// Append a child node the the XML object
@@ -175,10 +177,7 @@
     /// node is placed in the new tree structure after it is removed from
     /// its existing parent node. 
     ///
-    /// @param as
-    ///           The XMLNode_as ?
-    ///
-    /// @param node
+    /// @param childNode
     ///           same as XMLNode_as::obj ?
     ///
     void appendChild(boost::intrusive_ptr<XMLNode_as> childNode);
@@ -221,14 +220,11 @@
     ///                 for XML.sendAndLoad.
     virtual void toString(std::ostream& str, bool encode = false) const;
 
-    // We might turn this back to a dumb pointer, as long
-    // as we'll make sure in the XMLNode destructor and
-    // any child cleaning interface to set child parent
-    // to NULL
-    boost::intrusive_ptr<XMLNode_as> _parent;
-
-    Children _children;
-    Attributes _attributes;
+    as_object* getAttributes() { return _attributes; }
+
+    const as_object* getAttributes() const { return _attributes; }
+
+    void setAttribute(const std::string& name, const std::string& value);
 
 protected:
 
@@ -243,15 +239,19 @@
        virtual void markReachableResources() const;
 #endif // GNASH_USE_GC
 
+    Children _children;
+
 private:
 
-    // TODO: make a lot more things private !
+    boost::intrusive_ptr<XMLNode_as> _parent;
+
+    as_object* _attributes;
 
     std::string _name;
 
     std::string _value;
 
-    NodeType     _type;
+    NodeType _type;
 
     std::string _namespaceURI;
 

=== modified file 'libcore/asobj/XML_as.cpp'
--- a/libcore/asobj/XML_as.cpp  2008-11-19 08:41:47 +0000
+++ b/libcore/asobj/XML_as.cpp  2008-11-21 11:10:23 +0000
@@ -209,7 +209,7 @@
 
 void
 XML_as::parseAttribute(XMLNode_as* node, const std::string& xml,
-        std::string::const_iterator& it)
+        std::string::const_iterator& it, Attributes& attributes)
 {
 
     const std::string terminators("\r\t\n >=");
@@ -275,14 +275,14 @@
     // Handle namespace. This is set once only for each node, and is also
     // pushed to the attributes list once.
     StringNoCaseEqual noCaseCompare;
-    if (noCaseCompare(name, "xmlns")) {
+    if (noCaseCompare(name, "xmlns") || noCaseCompare(name, "xmlns:")) {
         if (!node->getNamespaceURI().empty()) return;
         node->setNamespaceURI(value);
     }
 
-    XMLAttr attr(name, value);
-    node->_attributes.push_back(attr);
-
+    // This ensures values are not inserted twice, which is expected
+    // behaviour
+    attributes.insert(std::make_pair(name, value));
 
 }
 
@@ -370,12 +370,14 @@
 
         // Parse any attributes in an opening tag only, stopping at "/>" or
         // '>'
+        // Attributes are added in reverse order and without any duplicates.
+        Attributes attributes;
         while (it != xml.end() && *it != '>' && _status == XML_OK)
         {
             if (xml.end() - it > 1 && std::equal(it, it + 2, "/>")) break;
 
             // This advances the iterator
-            parseAttribute(childNode, xml, it);
+            parseAttribute(childNode, xml, it, attributes);
 
             // Skip any whitespace. If we reach the end of the string,
             // it's malformed.
@@ -384,6 +386,11 @@
                 return;
             }
         }
+        
+        for (Attributes::const_reverse_iterator i = attributes.rbegin(),
+                e = attributes.rend(); i != e; ++i) {
+            childNode->setAttribute(i->first, i->second);
+        }
 
         node->appendChild(childNode);
         if (*it == '/') ++it;
@@ -556,7 +563,7 @@
 {
     // TODO: should set childs's parent to NULL ?
     _children.clear();
-    _attributes.clear();
+    //_attributes.clear();
     _docTypeDecl.clear();
     _xmlDecl.clear();
 }

=== modified file 'libcore/asobj/XML_as.h'
--- a/libcore/asobj/XML_as.h    2008-11-19 08:41:47 +0000
+++ b/libcore/asobj/XML_as.h    2008-11-21 09:51:27 +0000
@@ -22,6 +22,7 @@
 #include "XMLNode_as.h"
 #include "log.h"
 #include "dsodefs.h"
+#include "StringPredicates.h"
 
 #include <map>
 #include <string>
@@ -109,27 +110,6 @@
     ///
     void parseXML(const std::string& xml);
 
-    void parseTag(XMLNode_as*& node, const std::string& xml, 
-            std::string::const_iterator& it);
-
-    void parseAttribute(XMLNode_as* node, const std::string& xml, 
-            std::string::const_iterator& it);
-
-    void parseDocTypeDecl(const std::string& xml, 
-            std::string::const_iterator& it);
-
-    void parseText(XMLNode_as* node, const std::string& xml, 
-            std::string::const_iterator& it);
-
-    void parseXMLDecl(const std::string& xml, 
-            std::string::const_iterator& it);
-
-    void parseComment(XMLNode_as* node, const std::string& xml, 
-            std::string::const_iterator& it);
-
-    void parseCData(XMLNode_as* node, const std::string& xml, 
-            std::string::const_iterator& it);
- 
     // An event handler that returns a what?
     bool onLoad();
 
@@ -153,6 +133,29 @@
 
     static const Entities& getEntities();
 
+    typedef std::map<std::string, std::string, StringNoCaseLessThen> 
Attributes;
+
+    void parseTag(XMLNode_as*& node, const std::string& xml, 
+            std::string::const_iterator& it);
+
+    void parseAttribute(XMLNode_as* node, const std::string& xml, 
+            std::string::const_iterator& it, Attributes& attributes);
+
+    void parseDocTypeDecl(const std::string& xml, 
+            std::string::const_iterator& it);
+
+    void parseText(XMLNode_as* node, const std::string& xml, 
+            std::string::const_iterator& it);
+
+    void parseXMLDecl(const std::string& xml, 
+            std::string::const_iterator& it);
+
+    void parseComment(XMLNode_as* node, const std::string& xml, 
+            std::string::const_iterator& it);
+
+    void parseCData(XMLNode_as* node, const std::string& xml, 
+            std::string::const_iterator& it);
+ 
     /// Remove all children
     void clear();
   

=== modified file 'testsuite/actionscript.all/XMLNode.as'
--- a/testsuite/actionscript.all/XMLNode.as     2008-11-20 17:50:40 +0000
+++ b/testsuite/actionscript.all/XMLNode.as     2008-11-21 11:10:23 +0000
@@ -204,23 +204,35 @@
 
 check_equals(typeof(node2.attributes), "object");
 node2.attributes[3] = "a3";
-xcheck_equals(node2.attributes[3], "a3");
-xcheck_equals(node2.attributes["3"], "a3");
+check_equals(node2.attributes[3], "a3");
+check_equals(node2.attributes["3"], "a3");
 node2.attributes.a = "aa";
-xcheck_equals(node2.attributes.a, "aa");
-xcheck_equals(node2.attributes["a"], "aa");
-xcheck_equals(node2.toString(), '<node2 a="aa" 3="a3">second text 
node</node2>');
+check_equals(node2.attributes.a, "aa");
+check_equals(node2.attributes["a"], "aa");
+check_equals(node2.toString(), '<node2 a="aa" 3="a3">second text 
node</node2>');
 
 // Seems not to be overwritable
 node2.attributes = 3;
-xcheck_equals(node2.toString(), '<node2 a="aa" 3="a3">second text 
node</node2>');
+check_equals(node2.toString(), '<node2 a="aa" 3="a3">second text 
node</node2>');
 
 ASSetPropFlags(XMLNode.prototype, "attributes", 0, 1);
 node77 = doc.createElement("tag");
 node77.attributes.a1 = "at1";
-xcheck_equals(node77.toString(), '<tag a1="at1" />');
+check_equals(node77.toString(), '<tag a1="at1" />');
 node77.attributes = 5;
-xcheck_equals(node77.toString(), '<tag a1="at1" />');
+check_equals(node77.toString(), '<tag a1="at1" />');
+
+// Check order of attributes:
+
+node77.attributes.z = "z";
+node77.attributes.x = "x";
+node77.attributes.c = "c";
+node77.attributes.y = "y";
+node77.attributes.f = "f";
+node77.attributes[5] = "5";
+node77.attributes["$"] = "$";
+node77.attributes.x = "x2";
+check_equals(node77.toString(), '<tag $="$" 5="5" f="f" y="y" c="c" x="x2" 
z="z" a1="at1" />');
 
 // Check namespace functions.
 
@@ -232,12 +244,12 @@
 check_equals(ns.attributes["xmlns"], "standard");
 check_equals(ns.namespaceURI, "standard");
 check_equals(ns.getNamespaceForPrefix(), undefined);
-xcheck_equals(ns.getNamespaceForPrefix(""), "standard");
-xcheck_equals(ns.getPrefixForNamespace("standard"), "");
+check_equals(ns.getNamespaceForPrefix(""), "standard");
+check_equals(ns.getPrefixForNamespace("standard"), "");
 
 ns.attributes["xmlns"] = "standard2";
 check_equals(ns.namespaceURI, "standard");
-xcheck_equals(ns.getNamespaceForPrefix(""), "standard2");
+check_equals(ns.getNamespaceForPrefix(""), "standard2");
 
 ns = ns.firstChild;
 check_equals(ns.nodeName, null);
@@ -249,8 +261,8 @@
 ns = x.firstChild;
 check_equals(ns.namespaceURI, "");
 check_equals(ns.getNamespaceForPrefix(), undefined);
-xcheck_equals(ns.getNamespaceForPrefix("t"), "standard");
-xcheck_equals(ns.getPrefixForNamespace("standard"), "t");
+check_equals(ns.getNamespaceForPrefix("t"), "standard");
+check_equals(ns.getPrefixForNamespace("standard"), "t");
 
 x = new XML('<tag xmlns:t="nst"><tag2 xmlns="nss"><tag3 
xmlns:r="nsr"></tag3></tag2></tag>');
 
@@ -260,8 +272,8 @@
 check_equals(n.getNamespaceForPrefix("r"), undefined);
 check_equals(n.getPrefixForNamespace("nsr"), undefined);
 check_equals(n.getNamespaceForPrefix(), undefined);
-xcheck_equals(n.getNamespaceForPrefix("t"), "nst");
-xcheck_equals(n.getPrefixForNamespace("nst"), "t");
+check_equals(n.getNamespaceForPrefix("t"), "nst");
+check_equals(n.getPrefixForNamespace("nst"), "t");
 
 n = n.firstChild;
 check_equals(n.nodeName, "tag2");
@@ -269,17 +281,28 @@
 check_equals(n.getNamespaceForPrefix(), undefined);
 check_equals(n.getNamespaceForPrefix("r"), undefined);
 check_equals(n.getPrefixForNamespace("nsr"), undefined);
-xcheck_equals(n.getNamespaceForPrefix("t"), "nst");
-xcheck_equals(n.getPrefixForNamespace("nst"), "t");
+check_equals(n.getNamespaceForPrefix("t"), "nst");
+check_equals(n.getPrefixForNamespace("nst"), "t");
 
 n = n.firstChild;
 check_equals(n.nodeName, "tag3");
 check_equals(n.namespaceURI, "nss");
 check_equals(n.getNamespaceForPrefix(), undefined);
-xcheck_equals(n.getNamespaceForPrefix("r"), "nsr");
-xcheck_equals(n.getPrefixForNamespace("nsr"), "r");
-xcheck_equals(n.getNamespaceForPrefix("t"), "nst");
-xcheck_equals(n.getPrefixForNamespace("nst"), "t");
+check_equals(n.getNamespaceForPrefix("r"), "nsr");
+check_equals(n.getPrefixForNamespace("nsr"), "r");
+check_equals(n.getNamespaceForPrefix("t"), "nst");
+check_equals(n.getPrefixForNamespace("nst"), "t");
+
+// Poorly formed prefix namespaces: become standard namespaces
+x = new XML('<tag xmlns:="nst"><tag2 xmlns="nss"><tag3 
xmlns:="nsr"></tag3></tag2></tag>');
+
+n = x.firstChild.firstChild.firstChild;
+check_equals(n.nodeName, "tag3");
+check_equals(n.namespaceURI, "nsr");
+check_equals(n.getPrefixForNamespace("nsr"), "");
+check_equals(n.getNamespaceForPrefix(), undefined);
+check_equals(n.getPrefixForNamespace("nst"), "");
+
 
 // Multiple definition of standard namespace (first one counts, second never
 // defined).
@@ -288,8 +311,9 @@
 check_equals(ns.nodeName, "tag");
 check_equals(ns.attributes["xmlns"], "standard");
 check_equals(ns.namespaceURI, "standard");
-xcheck_equals(ns.getNamespaceForPrefix(""), "standard");
-xcheck_equals(ns.getPrefixForNamespace("standard"), "");
+check_equals(ns.getNamespaceForPrefix(""), "standard");
+
+check_equals(ns.getPrefixForNamespace("standard"), "");
 check_equals(ns.getPrefixForNamespace("standard2"), undefined);
 
 // Multiple definition of prefix during parsing (first one counts,
@@ -298,17 +322,17 @@
 ns = x.firstChild;
 check_equals(ns.nodeName, "tag");
 check_equals(ns.attributes["xmlns"], undefined);
-xcheck_equals(ns.attributes["xmlns:n1"], "ns1");
+check_equals(ns.attributes["xmlns:n1"], "ns1");
 check_equals(ns.namespaceURI, "");
-xcheck_equals(ns.getNamespaceForPrefix("n1"), "ns1");
-xcheck_equals(ns.getPrefixForNamespace("ns1"), "n1");
+check_equals(ns.getNamespaceForPrefix("n1"), "ns1");
+check_equals(ns.getPrefixForNamespace("ns1"), "n1");
 check_equals(ns.getPrefixForNamespace("ns2"), undefined);
 
 ns.attributes["xmlns:n1"] = "ns2";
 check_equals(ns.attributes["xmlns:n1"], "ns2");
-xcheck_equals(ns.getNamespaceForPrefix("n1"), "ns2");
+check_equals(ns.getNamespaceForPrefix("n1"), "ns2");
 check_equals(ns.getPrefixForNamespace("ns1"), undefined);
-xcheck_equals(ns.getPrefixForNamespace("ns2"), "n1");
+check_equals(ns.getPrefixForNamespace("ns2"), "n1");
 
 // Setting via attributes
 x = new XML('<tag></tag>');
@@ -317,7 +341,7 @@
 check_equals(ns.attributes["xmlns"], undefined);
 check_equals(ns.namespaceURI, "");
 ns.attributes["xmlns"] = "nss";
-xcheck_equals(ns.attributes["xmlns"], "nss");
+check_equals(ns.attributes["xmlns"], "nss");
 check_equals(ns.namespaceURI, "");
 
 /// Prefix, localName
@@ -357,4 +381,4 @@
 check_equals(ns.localName, "tag");
 check_equals(ns.prefix, "");
 
-check_totals(169);
+check_totals(175);


reply via email to

[Prev in Thread] Current Thread [Next in Thread]