1 // XMLNode_as.cpp: ActionScript "XMLNode" class, for Gnash.
3 // Copyright (C) 2009, 2010 Free Software Foundation, Inc.
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "XMLNode_as.h"
26 #include "Global_as.h"
27 #include "smart_ptr.h" // for boost intrusive_ptr
28 #include "builtin_function.h" // need builtin_function
29 #include "NativeFunction.h"
31 #include "PropertyList.h"
32 #include "Global_as.h"
36 #include "namedStrings.h"
37 #include <boost/bind.hpp>
45 // Function Prototypes
47 typedef std::pair
<std::string
, std::string
> StringPair
;
48 typedef std::vector
<StringPair
> StringPairs
;
49 void enumerateAttributes(const XMLNode_as
& node
,
50 StringPairs
& attributes
);
51 bool prefixMatches(const StringPairs::value_type
& val
,
52 const std::string
& prefix
);
53 bool namespaceMatches(
54 const StringPairs::value_type
& val
,
55 const std::string
& ns
);
57 as_value
xmlnode_new(const fn_call
& fn
);
58 as_value
xmlnode_nodeName(const fn_call
& fn
);
59 as_value
xmlnode_nodeValue(const fn_call
& fn
);
60 as_value
xmlnode_nodeType(const fn_call
& fn
);
61 as_value
xmlnode_attributes(const fn_call
& fn
);
62 as_value
xmlnode_appendChild(const fn_call
& fn
);
63 as_value
xmlnode_cloneNode(const fn_call
& fn
);
64 as_value
xmlnode_lastChild(const fn_call
& fn
);
65 as_value
xmlnode_firstChild(const fn_call
& fn
);
66 as_value
xmlnode_nextSibling(const fn_call
& fn
);
67 as_value
xmlnode_childNodes(const fn_call
& fn
);
68 as_value
xmlnode_previousSibling(const fn_call
& fn
);
69 as_value
xmlnode_parentNode(const fn_call
& fn
);
70 as_value
xmlnode_getNamespaceForPrefix(const fn_call
& fn
);
71 as_value
xmlnode_getPrefixForNamespace(const fn_call
& fn
);
72 as_value
xmlnode_namespaceURI(const fn_call
& fn
);
73 as_value
xmlnode_hasChildNodes(const fn_call
& fn
);
74 as_value
xmlnode_insertBefore(const fn_call
& fn
);
75 as_value
xmlnode_removeNode(const fn_call
& fn
);
76 as_value
xmlnode_toString(const fn_call
& fn
);
77 as_value
xmlnode_localName(const fn_call
& fn
);
78 as_value
xmlnode_prefix(const fn_call
& fn
);
79 void attachXMLNodeInterface(as_object
& o
);
82 XMLNode_as::XMLNode_as(Global_as
& gl
)
87 _attributes(new as_object(gl
)),
93 XMLNode_as::XMLNode_as(const XMLNode_as
& tpl
, bool deep
)
98 _attributes(new as_object(_global
)),
104 // only clone children if in deep mode
106 const Children
& from
=tpl
._children
;
107 for (Children::const_iterator it
=from
.begin(), itEnd
=from
.end();
109 _children
.push_back(new XMLNode_as(*(*it
), deep
));
114 XMLNode_as::~XMLNode_as()
123 // This is almost the same as if the XMLNode constructor were called,
124 // but not quite. There is no __constructor__ property, and when we
125 // override _global.XMLNode, we can show that it is not called.
127 as_object
* o
= createObject(_global
);
129 toObject(getMember(_global
, NSV::CLASS_XMLNODE
), getVM(_global
));
131 o
->set_prototype(getMember(*xn
, NSV::PROP_PROTOTYPE
));
132 o
->init_member(NSV::PROP_CONSTRUCTOR
, xn
);
141 XMLNode_as::updateChildNodes()
143 if (!_childNodes
) return;
145 // Clear array of all elements.
146 _childNodes
->set_member(NSV::PROP_LENGTH
, 0.0);
148 if (_children
.empty()) return;
150 VM
& vm
= getVM(_global
);
152 // Set up the array without calling push()!
153 const size_t size
= _children
.size();
154 Children::const_iterator it
= _children
.begin();
155 for (size_t i
= 0; i
!= size
; ++i
, ++it
) {
156 XMLNode_as
* node
= *it
;
157 const ObjectURI
& key
= arrayKey(vm
, i
);
158 _childNodes
->set_member(key
, node
->object());
160 // All elements are set to readonly.
161 _childNodes
->set_member_flags(key
, PropFlags::readOnly
);
166 XMLNode_as::childNodes()
169 _childNodes
= _global
.createArray();
176 XMLNode_as::hasChildNodes()
178 return !_children
.empty();
182 XMLNode_as::firstChild()
184 if (_children
.empty()) return 0;
185 return _children
.front();
189 XMLNode_as::cloneNode(bool deep
)
191 XMLNode_as
* newnode
= new XMLNode_as(*this, deep
);
196 XMLNode_as::lastChild()
198 if (_children
.empty()) {
199 log_debug(_("XMLNode_as %p has no children"), (void*)this);
202 return _children
.back();
206 XMLNode_as::removeChild(XMLNode_as
* node
)
209 _children
.remove(node
);
214 XMLNode_as::appendChild(XMLNode_as
* node
)
217 node
->setParent(this);
218 _children
.push_back(node
);
223 XMLNode_as::insertBefore(XMLNode_as
* newnode
, XMLNode_as
* pos
)
227 // find iterator for positional parameter
228 Children::iterator it
= std::find(_children
.begin(), _children
.end(), pos
);
229 if (it
== _children
.end()) {
230 IF_VERBOSE_ASCODING_ERRORS(
231 log_aserror(_("XMLNode.insertBefore(): positional parameter "
232 "is not a child of this node"));
237 _children
.insert(it
, newnode
);
239 XMLNode_as
* parent
= newnode
->getParent();
241 parent
->removeChild(newnode
);
244 newnode
->setParent(this);
249 XMLNode_as::previousSibling()
251 if (!_parent
) return 0;
252 if (_parent
->_children
.size() <= 1) return 0;
254 XMLNode_as
*previous_node
= 0;
255 for (Children::iterator itx
= _parent
->_children
.begin();
256 itx
!= _parent
->_children
.end(); itx
++) {
258 if (*itx
== this) return previous_node
;
260 previous_node
= *itx
;
267 XMLNode_as::nextSibling()
270 if (!_parent
) return 0;
272 if (_parent
->_children
.size() <= 1) return 0;
274 XMLNode_as
*previous_node
= 0;
275 for (Children::reverse_iterator itx
= _parent
->_children
.rbegin();
276 itx
!= _parent
->_children
.rend(); ++itx
) {
278 if (*itx
== this) return previous_node
;
279 previous_node
= *itx
;
286 XMLNode_as::toString(std::ostream
& xmlout
, bool encode
) const
288 stringify(*this, xmlout
, encode
);
292 XMLNode_as::setAttribute(const std::string
& name
, const std::string
& value
)
295 VM
& vm
= getVM(_global
);
296 _attributes
->set_member(getURI(vm
, name
), value
);
301 XMLNode_as::getPrefixForNamespace(const std::string
& ns
, std::string
& prefix
)
303 XMLNode_as
* node
= this;
304 StringPairs::const_iterator it
;
308 enumerateAttributes(*node
, attrs
);
311 it
= std::find_if(attrs
.begin(), attrs
.end(),
312 boost::bind(namespaceMatches
, _1
, ns
));
313 if (it
!= attrs
.end()) break;
315 node
= node
->getParent();
319 if (!node
) return false;
321 // Return the matching prefix
322 const std::string
& name
= it
->first
;
324 if (name
.length() == 5) {
328 assert (name
.length() >= 6);
330 if (name
[5] != ':') return false;
332 // Can also be empty.
333 prefix
= name
.substr(6);
338 XMLNode_as::getNamespaceForPrefix(const std::string
& prefix
, std::string
& ns
)
340 XMLNode_as
* node
= this;
341 StringPairs::const_iterator it
;
346 enumerateAttributes(*node
, attrs
);
348 if (!attrs
.empty()) {
350 it
= std::find_if(attrs
.begin(), attrs
.end(),
351 boost::bind(prefixMatches
, _1
, prefix
));
352 if (it
!= attrs
.end()) break;
354 node
= node
->getParent();
357 // None found; return undefined
360 // Return the matching namespace
366 XMLNode_as::extractPrefix(std::string
& prefix
)
369 if (_name
.empty()) return false;
371 std::string::size_type pos
= _name
.find(':');
372 if (pos
== std::string::npos
|| pos
== _name
.size() - 1) {
376 prefix
= _name
.substr(0, pos
);
381 XMLNode_as::clearChildren()
383 for (Children::const_iterator it
= _children
.begin(), e
= _children
.end();
385 const XMLNode_as
* node
= *it
;
386 if (!node
->_object
) {
392 // Reset so that it is reinitialized on next access.
397 XMLNode_as::stringify(const XMLNode_as
& xml
, std::ostream
& xmlout
, bool encode
)
400 const std::string
& nodeValue
= xml
.nodeValue();
401 const std::string
& nodeName
= xml
.nodeName();
402 NodeType type
= xml
.nodeType();
405 log_debug(_("Stringifying node %p with name %s, as_value %s, %u "
406 "attributes and %u children"), (void*)&xml
, nodeName
,
407 nodeValue
, xml
._attributes
.size(), xml
._children
.size());
410 // Create the beginning of the tag
411 if (!nodeName
.empty()) {
413 xmlout
<< "<" << nodeName
;
415 // Process the attributes, if any
417 enumerateAttributes(xml
, attrs
);
418 if (!attrs
.empty()) {
420 for (StringPairs::iterator i
=
421 attrs
.begin(), e
= attrs
.end(); i
!= e
; ++i
) {
422 escapeXML(i
->second
);
423 xmlout
<< " " << i
->first
<< "=\"" << i
->second
<< "\"";
427 // If the node has no content, just close the tag now
428 if (nodeValue
.empty() && xml
._children
.empty()) {
433 // Will use a closing tag later
439 // Node as_value first, then children
442 Global_as
& gl
= xml
._global
;
445 std::string
escaped(nodeValue
);
447 const std::string
& val
= encode
?
448 callMethod(&gl
, NSV::PROP_ESCAPE
, escaped
).to_string() :
454 // Childs, after node as_value.
455 for (Children::const_iterator itx
= xml
._children
.begin();
456 itx
!= xml
._children
.end(); ++itx
) {
458 (*itx
)->toString(xmlout
, encode
);
461 if (!nodeName
.empty()) {
462 xmlout
<< "</" << nodeName
<< ">";
467 XMLNode_as::setReachable()
469 // If there is a parent, make sure its object is reachable. This goes
470 // up towards the root node of tree without marking the XMLNode
471 // resources (which would cause infinite recursion).
472 if (_parent
&& _parent
->_object
) _parent
->_object
->setReachable();
475 std::for_each(_children
.begin(), _children
.end(),
476 boost::mem_fn(&XMLNode_as::setReachable
));
478 // Mark attributes object
479 if (_attributes
) _attributes
->setReachable();
481 if (_object
) _object
->setReachable();
483 if (_childNodes
) _childNodes
->setReachable();
488 registerXMLNodeNative(as_object
& where
)
490 VM
& vm
= getVM(where
);
491 vm
.registerNative(xmlnode_cloneNode
, 253, 1);
492 vm
.registerNative(xmlnode_removeNode
, 253, 2);
493 vm
.registerNative(xmlnode_insertBefore
, 253, 3);
494 vm
.registerNative(xmlnode_appendChild
, 253, 4);
495 vm
.registerNative(xmlnode_hasChildNodes
, 253, 5);
496 vm
.registerNative(xmlnode_toString
, 253, 6);
497 vm
.registerNative(xmlnode_getNamespaceForPrefix
, 253, 7);
498 vm
.registerNative(xmlnode_getPrefixForNamespace
, 253, 8);
502 xmlnode_class_init(as_object
& where
, const ObjectURI
& uri
)
504 Global_as
& gl
= getGlobal(where
);
505 as_object
* proto
= createObject(gl
);
506 attachXMLNodeInterface(*proto
);
507 as_object
* cl
= gl
.createClass(&xmlnode_new
, proto
);
509 where
.init_member(uri
, cl
, as_object::DefaultFlags
);
516 attachXMLNodeInterface(as_object
& o
)
521 const int noFlags
= 0;
524 o
.init_member("cloneNode", vm
.getNative(253, 1), noFlags
);
525 o
.init_member("removeNode", vm
.getNative(253, 2), noFlags
);
526 o
.init_member("insertBefore", vm
.getNative(253, 3), noFlags
);
527 o
.init_member("appendChild", vm
.getNative(253, 4), noFlags
);
528 o
.init_member("hasChildNodes", vm
.getNative(253, 5), noFlags
);
529 o
.init_member("toString", vm
.getNative(253, 6), noFlags
);
530 o
.init_member("getNamespaceForPrefix", vm
.getNative(253, 7), noFlags
);
531 o
.init_member("getPrefixForNamespace", vm
.getNative(253, 8), noFlags
);
533 const int protectedFlags
= 0;
535 // Just the protected flag:
537 o
.init_readonly_property("attributes", &xmlnode_attributes
, protectedFlags
);
538 o
.init_readonly_property("childNodes", &xmlnode_childNodes
, protectedFlags
);
539 o
.init_readonly_property("firstChild", &xmlnode_firstChild
, protectedFlags
);
540 o
.init_readonly_property("lastChild", &xmlnode_lastChild
, protectedFlags
);
541 o
.init_readonly_property("nextSibling",
542 &xmlnode_nextSibling
, protectedFlags
);
543 o
.init_property("nodeName", &xmlnode_nodeName
,
544 &xmlnode_nodeName
, protectedFlags
);
545 o
.init_readonly_property("nodeType", &xmlnode_nodeType
, protectedFlags
);
546 o
.init_property("nodeValue", &xmlnode_nodeValue
,
547 &xmlnode_nodeValue
, protectedFlags
);
548 o
.init_readonly_property("parentNode", &xmlnode_parentNode
, protectedFlags
);
549 o
.init_readonly_property("previousSibling",
550 &xmlnode_previousSibling
, protectedFlags
);
551 o
.init_readonly_property("prefix", &xmlnode_prefix
, protectedFlags
);
552 o
.init_readonly_property("localName", &xmlnode_localName
, protectedFlags
);
553 o
.init_readonly_property("namespaceURI",
554 &xmlnode_namespaceURI
, protectedFlags
);
559 xmlnode_new(const fn_call
& fn
)
562 as_object
* obj
= ensure
<ValidThis
>(fn
);
568 std::auto_ptr
<XMLNode_as
> xml(new XMLNode_as(getGlobal(fn
)));
569 xml
->nodeTypeSet(XMLNode_as::NodeType(toInt(fn
.arg(0), getVM(fn
))));
572 const std::string
& str
= fn
.arg(1).to_string();
573 switch (xml
->nodeType())
575 case XMLNode_as::Element
:
576 xml
->nodeNameSet(str
);
579 xml
->nodeValueSet(str
);
584 // This sets the relay!
586 obj
->setRelay(xml
.release());
593 xmlnode_appendChild(const fn_call
& fn
)
596 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
599 IF_VERBOSE_ASCODING_ERRORS(
600 log_aserror(_("XMLNode::appendChild() needs at least one "
607 if (!isNativeType(toObject(fn
.arg(0), getVM(fn
)), node
)) {
608 IF_VERBOSE_ASCODING_ERRORS(
609 log_aserror(_("First argument to XMLNode::appendChild() is not "
615 XMLNode_as
* parent
= node
->getParent();
617 parent
->removeChild(node
);
619 ptr
->appendChild(node
);
626 xmlnode_cloneNode(const fn_call
& fn
)
628 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
631 if (fn
.nargs
> 0) deep
= toBool(fn
.arg(0), getVM(fn
));
633 as_object
* newnode
= ptr
->cloneNode(deep
)->object();
634 return as_value(newnode
);
639 xmlnode_insertBefore(const fn_call
& fn
)
641 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
645 IF_VERBOSE_ASCODING_ERRORS(
646 std::stringstream ss
; fn
.dump_args(ss
);
647 log_aserror(_("XMLNode.insertBefore(%s) needs at least two "
648 "arguments"), ss
.str());
655 if (!isNativeType(toObject(fn
.arg(0), getVM(fn
)), newnode
)) {
656 IF_VERBOSE_ASCODING_ERRORS(
657 std::stringstream ss
; fn
.dump_args(ss
);
658 log_aserror(_("First argument to XMLNode.insertBefore(%s) is not "
659 "an XMLNode"), ss
.str());
666 if (!isNativeType(toObject(fn
.arg(1), getVM(fn
)), pos
)) {
667 IF_VERBOSE_ASCODING_ERRORS(
668 std::stringstream ss
; fn
.dump_args(ss
);
669 log_aserror(_("Second argument to XMLNode.insertBefore(%s) is not "
670 "an XMLNode"), ss
.str());
675 ptr
->insertBefore(newnode
, pos
);
682 xmlnode_getNamespaceForPrefix(const fn_call
& fn
)
684 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
691 ptr
->getNamespaceForPrefix(fn
.arg(0).to_string(), ns
);
692 if (ns
.empty()) return as_value();
698 xmlnode_getPrefixForNamespace(const fn_call
& fn
)
700 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
707 // Return undefined if none found; otherwise the prefix string found.
708 // This can be empty if it is a standard namespace.
709 if (!ptr
->getPrefixForNamespace(fn
.arg(0).to_string(), prefix
)) {
712 return as_value(prefix
);
715 /// If the node has a prefix, return the matching namespace. Otherwise,
716 /// returns a namespaceURI set with the xmlns attribute, searching upwards
717 /// through parent nodes if necessary.
719 /// This standard namespace can only be set during XML parsing and cannot
720 /// be changed or set using attributes.
722 /// Conversely, the similar getNamespaceForPrefix("") can be set and changed
723 /// through attributes.
725 xmlnode_namespaceURI(const fn_call
& fn
)
727 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
729 // Read-only property
731 const std::string
& name
= ptr
->nodeName();
740 if (ptr
->extractPrefix(prefix
)) {
742 ptr
->getNamespaceForPrefix(prefix
, ns
);
746 // Search recursively for a namespace. Return an empty string
748 XMLNode_as
* node
= ptr
;
749 while (node
&& node
->getNamespaceURI().empty()) {
750 node
= node
->getParent();
752 if (!node
) return as_value("");
754 return as_value(node
->getNamespaceURI());
758 // Return the prefix part of the node name. If there is no colon, or one
759 // colon at the end of the string, this is empty. Otherwise it is the part
760 // up to the first colon.
762 xmlnode_prefix(const fn_call
& fn
)
764 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
766 // Read-only property
768 if (ptr
->nodeName().empty()) {
775 if (!ptr
->extractPrefix(prefix
)) return as_value("");
776 return as_value(prefix
);
780 // The local part of a node name. If there is no colon or a single colon
781 // at the end of the string, this is the whole string. Otherwise all of the
782 // string after the first colon.
784 xmlnode_localName(const fn_call
& fn
)
786 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
788 // Read-only property
790 if (ptr
->nodeName().empty()) {
796 const std::string
& nodeName
= ptr
->nodeName();
797 if (nodeName
.empty()) return as_value("");
799 std::string::size_type pos
= nodeName
.find(':');
800 if (pos
== std::string::npos
|| pos
== nodeName
.size() - 1) {
801 return as_value(nodeName
);
804 return as_value(nodeName
.substr(pos
+ 1));
809 xmlnode_removeNode(const fn_call
& fn
)
811 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
813 XMLNode_as
* parent
= ptr
->getParent();
814 if (parent
) parent
->removeChild(ptr
);
820 xmlnode_toString(const fn_call
& fn
)
823 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
825 std::stringstream ss
;
828 return as_value(ss
.str());
833 xmlnode_hasChildNodes(const fn_call
& fn
)
835 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
836 return as_value(ptr
->hasChildNodes());
841 xmlnode_nodeValue(const fn_call
& fn
)
843 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
849 const std::string
& val
= ptr
->nodeValue();
850 if ( ! val
.empty() ) rv
= val
;
854 ptr
->nodeValueSet(fn
.arg(0).to_string());
861 xmlnode_nodeName(const fn_call
& fn
)
863 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
868 const std::string
& val
= ptr
->nodeName();
869 if ( ! val
.empty() ) rv
= val
;
872 ptr
->nodeNameSet(fn
.arg(0).to_string());
879 xmlnode_nodeType(const fn_call
& fn
)
881 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
882 return as_value(ptr
->nodeType());
887 xmlnode_attributes(const fn_call
& fn
)
889 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
891 as_object
* attrs
= ptr
->getAttributes();
892 if (attrs
) return as_value(attrs
);
897 /// Read-only property; evaluates the specified XML object and
898 /// references the first child in the parent node's child
899 /// list. This property is null if the node does not have
900 /// children. This property is undefined if the node is a text
901 /// node. This is a read-only property and cannot be used to
902 /// manipulate child nodes; use the appendChild(), insertBefore(),
903 /// and removeNode() methods to manipulate child nodes.
906 xmlnode_firstChild(const fn_call
& fn
)
908 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
912 XMLNode_as
* node
= ptr
->firstChild();
921 /// Read-only property; an XMLNode as_value that references the last
922 /// child in the node's child list. The XML.lastChild property
923 /// is null if the node does not have children. This property cannot
924 /// be used to manipulate child nodes; use the appendChild(),
925 /// insertBefore(), and removeNode() methods to manipulate child
928 xmlnode_lastChild(const fn_call
& fn
)
930 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
934 XMLNode_as
* node
= ptr
->lastChild();
944 xmlnode_nextSibling(const fn_call
& fn
)
949 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
950 XMLNode_as
*node
= ptr
->nextSibling();
959 xmlnode_previousSibling(const fn_call
& fn
)
964 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
965 XMLNode_as
*node
= ptr
->previousSibling();
974 xmlnode_parentNode(const fn_call
& fn
)
979 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
980 XMLNode_as
* node
= ptr
->getParent();
988 xmlnode_childNodes(const fn_call
& fn
)
990 XMLNode_as
* ptr
= ensure
<ThisIsNative
<XMLNode_as
> >(fn
);
991 return ptr
->childNodes();
996 enumerateAttributes(const XMLNode_as
& node
, StringPairs
& pairs
)
1000 as_object
* obj
= node
.getAttributes();
1002 string_table
& st
= getStringTable(*obj
);
1003 SortedPropertyList attrs
= enumerateProperties(*obj
);
1004 for (SortedPropertyList::const_reverse_iterator i
= attrs
.rbegin(),
1005 e
= attrs
.rend(); i
!= e
; ++i
) {
1006 // TODO: second argument should take version.
1008 std::make_pair(i
->first
.toString(st
), i
->second
.to_string()));
1014 /// Return true if this attribute is a namespace specifier and the
1015 /// namespace matches.
1017 namespaceMatches(const StringPairs::value_type
& val
,
1018 const std::string
& ns
)
1020 StringNoCaseEqual noCaseCompare
;
1021 return (noCaseCompare(val
.first
.substr(0, 5), "xmlns") &&
1022 noCaseCompare(val
.second
, ns
));
1027 prefixMatches(const StringPairs::value_type
& val
,
1028 const std::string
& prefix
)
1030 const std::string
& name
= val
.first
;
1031 StringNoCaseEqual noCaseCompare
;
1033 // An empty prefix searches for a standard namespace specifier.
1034 // Attributes are stored with no trailing or leading whitespace,
1035 // so a simple comparison should do. TODO: what about "xmlns:"?
1036 if (prefix
.empty()) {
1037 return noCaseCompare(name
, "xmlns") || noCaseCompare(name
, "xmlns:");
1040 if (!noCaseCompare(name
.substr(0, 6), "xmlns:")) return false;
1042 return noCaseCompare(prefix
, name
.substr(6));
1045 } // anonymous namespace
1046 } // gnash namespace
1049 // indent-tabs-mode: t