diff options
author | orivej <orivej@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:44:49 +0300 |
commit | 718c552901d703c502ccbefdfc3c9028d608b947 (patch) | |
tree | 46534a98bbefcd7b1f3faa5b52c138ab27db75b7 /contrib/libs/poco/XML/src/AbstractContainerNode.cpp | |
parent | e9656aae26e0358d5378e5b63dcac5c8dbe0e4d0 (diff) | |
download | ydb-718c552901d703c502ccbefdfc3c9028d608b947.tar.gz |
Restoring authorship annotation for <orivej@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/libs/poco/XML/src/AbstractContainerNode.cpp')
-rw-r--r-- | contrib/libs/poco/XML/src/AbstractContainerNode.cpp | 1146 |
1 files changed, 573 insertions, 573 deletions
diff --git a/contrib/libs/poco/XML/src/AbstractContainerNode.cpp b/contrib/libs/poco/XML/src/AbstractContainerNode.cpp index 52134ce09c..c891f155fe 100644 --- a/contrib/libs/poco/XML/src/AbstractContainerNode.cpp +++ b/contrib/libs/poco/XML/src/AbstractContainerNode.cpp @@ -1,573 +1,573 @@ -// -// AbstractContainerNode.cpp -// -// Library: XML -// Package: DOM -// Module: DOM -// -// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. -// and Contributors. -// -// SPDX-License-Identifier: BSL-1.0 -// - - -#include "Poco/DOM/AbstractContainerNode.h" -#include "Poco/DOM/Document.h" -#include "Poco/DOM/Element.h" -#include "Poco/DOM/Attr.h" -#include "Poco/DOM/DOMException.h" -#include "Poco/DOM/ElementsByTagNameList.h" -#include "Poco/DOM/AutoPtr.h" -#include "Poco/NumberParser.h" -#include "Poco/UnicodeConverter.h" - - -namespace Poco { -namespace XML { - - -const XMLString AbstractContainerNode::WILDCARD(toXMLString("*")); - - -AbstractContainerNode::AbstractContainerNode(Document* pOwnerDocument): - AbstractNode(pOwnerDocument), - _pFirstChild(0) -{ -} - - -AbstractContainerNode::AbstractContainerNode(Document* pOwnerDocument, const AbstractContainerNode& node): - AbstractNode(pOwnerDocument, node), - _pFirstChild(0) -{ -} - - -AbstractContainerNode::~AbstractContainerNode() -{ - AbstractNode* pChild = static_cast<AbstractNode*>(_pFirstChild); - while (pChild) - { - AbstractNode* pDelNode = pChild; - pChild = pChild->_pNext; - pDelNode->_pNext = 0; - pDelNode->_pParent = 0; - pDelNode->release(); - } -} - - -Node* AbstractContainerNode::firstChild() const -{ - return _pFirstChild; -} - - -Node* AbstractContainerNode::lastChild() const -{ - AbstractNode* pChild = _pFirstChild; - if (pChild) - { - while (pChild->_pNext) pChild = pChild->_pNext; - return pChild; - } - return 0; -} - - -Node* AbstractContainerNode::insertBefore(Node* newChild, Node* refChild) -{ - poco_check_ptr (newChild); - - if (static_cast<AbstractNode*>(newChild)->_pOwner != _pOwner && static_cast<AbstractNode*>(newChild)->_pOwner != this) - throw DOMException(DOMException::WRONG_DOCUMENT_ERR); - if (refChild && static_cast<AbstractNode*>(refChild)->_pParent != this) - throw DOMException(DOMException::NOT_FOUND_ERR); - if (newChild == refChild) - return newChild; - if (this == newChild) - throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); - - AbstractNode* pFirst = 0; - AbstractNode* pLast = 0; - if (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) - { - AbstractContainerNode* pFrag = static_cast<AbstractContainerNode*>(newChild); - pFirst = pFrag->_pFirstChild; - pLast = pFirst; - if (pFirst) - { - while (pLast->_pNext) - { - pLast->_pParent = this; - pLast = pLast->_pNext; - } - pLast->_pParent = this; - } - pFrag->_pFirstChild = 0; - } - else - { - newChild->duplicate(); - AbstractContainerNode* pParent = static_cast<AbstractNode*>(newChild)->_pParent; - if (pParent) pParent->removeChild(newChild); - pFirst = static_cast<AbstractNode*>(newChild); - pLast = pFirst; - pFirst->_pParent = this; - } - if (_pFirstChild && pFirst) - { - AbstractNode* pCur = _pFirstChild; - if (pCur == refChild) - { - pLast->_pNext = _pFirstChild; - _pFirstChild = pFirst; - } - else - { - while (pCur && pCur->_pNext != refChild) pCur = pCur->_pNext; - if (pCur) - { - pLast->_pNext = pCur->_pNext; - pCur->_pNext = pFirst; - } - else throw DOMException(DOMException::NOT_FOUND_ERR); - } - } - else _pFirstChild = pFirst; - - if (events()) - { - while (pFirst && pFirst != pLast->_pNext) - { - pFirst->dispatchNodeInserted(); - pFirst->dispatchNodeInsertedIntoDocument(); - pFirst = pFirst->_pNext; - } - dispatchSubtreeModified(); - } - return newChild; -} - - -Node* AbstractContainerNode::replaceChild(Node* newChild, Node* oldChild) -{ - poco_check_ptr (newChild); - poco_check_ptr (oldChild); - - if (static_cast<AbstractNode*>(newChild)->_pOwner != _pOwner && static_cast<AbstractNode*>(newChild)->_pOwner != this) - throw DOMException(DOMException::WRONG_DOCUMENT_ERR); - if (static_cast<AbstractNode*>(oldChild)->_pParent != this) - throw DOMException(DOMException::NOT_FOUND_ERR); - if (newChild == oldChild) - return newChild; - if (this == newChild) - throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); - - bool doEvents = events(); - if (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) - { - insertBefore(newChild, oldChild); - removeChild(oldChild); - } - else - { - AbstractContainerNode* pParent = static_cast<AbstractNode*>(newChild)->_pParent; - if (pParent) pParent->removeChild(newChild); - - if (oldChild == _pFirstChild) - { - if (doEvents) - { - _pFirstChild->dispatchNodeRemoved(); - _pFirstChild->dispatchNodeRemovedFromDocument(); - } - static_cast<AbstractNode*>(newChild)->_pNext = static_cast<AbstractNode*>(oldChild)->_pNext; - static_cast<AbstractNode*>(newChild)->_pParent = this; - _pFirstChild->_pNext = 0; - _pFirstChild->_pParent = 0; - _pFirstChild = static_cast<AbstractNode*>(newChild); - if (doEvents) - { - static_cast<AbstractNode*>(newChild)->dispatchNodeInserted(); - static_cast<AbstractNode*>(newChild)->dispatchNodeInsertedIntoDocument(); - } - } - else - { - AbstractNode* pCur = _pFirstChild; - while (pCur && pCur->_pNext != oldChild) pCur = pCur->_pNext; - if (pCur) - { - poco_assert_dbg (pCur->_pNext == oldChild); - - if (doEvents) - { - static_cast<AbstractNode*>(oldChild)->dispatchNodeRemoved(); - static_cast<AbstractNode*>(oldChild)->dispatchNodeRemovedFromDocument(); - } - static_cast<AbstractNode*>(newChild)->_pNext = static_cast<AbstractNode*>(oldChild)->_pNext; - static_cast<AbstractNode*>(newChild)->_pParent = this; - static_cast<AbstractNode*>(oldChild)->_pNext = 0; - static_cast<AbstractNode*>(oldChild)->_pParent = 0; - pCur->_pNext = static_cast<AbstractNode*>(newChild); - if (doEvents) - { - static_cast<AbstractNode*>(newChild)->dispatchNodeInserted(); - static_cast<AbstractNode*>(newChild)->dispatchNodeInsertedIntoDocument(); - } - } - else throw DOMException(DOMException::NOT_FOUND_ERR); - } - newChild->duplicate(); - oldChild->autoRelease(); - } - if (doEvents) dispatchSubtreeModified(); - return oldChild; -} - - -Node* AbstractContainerNode::removeChild(Node* oldChild) -{ - poco_check_ptr (oldChild); - - bool doEvents = events(); - if (oldChild == _pFirstChild) - { - if (doEvents) - { - static_cast<AbstractNode*>(oldChild)->dispatchNodeRemoved(); - static_cast<AbstractNode*>(oldChild)->dispatchNodeRemovedFromDocument(); - } - _pFirstChild = _pFirstChild->_pNext; - static_cast<AbstractNode*>(oldChild)->_pNext = 0; - static_cast<AbstractNode*>(oldChild)->_pParent = 0; - } - else - { - AbstractNode* pCur = _pFirstChild; - while (pCur && pCur->_pNext != oldChild) pCur = pCur->_pNext; - if (pCur) - { - if (doEvents) - { - static_cast<AbstractNode*>(oldChild)->dispatchNodeRemoved(); - static_cast<AbstractNode*>(oldChild)->dispatchNodeRemovedFromDocument(); - } - pCur->_pNext = pCur->_pNext->_pNext; - static_cast<AbstractNode*>(oldChild)->_pNext = 0; - static_cast<AbstractNode*>(oldChild)->_pParent = 0; - } - else throw DOMException(DOMException::NOT_FOUND_ERR); - } - oldChild->autoRelease(); - if (doEvents) dispatchSubtreeModified(); - return oldChild; -} - - -Node* AbstractContainerNode::appendChild(Node* newChild) -{ - return insertBefore(newChild, 0); -} - - -void AbstractContainerNode::dispatchNodeRemovedFromDocument() -{ - AbstractNode::dispatchNodeRemovedFromDocument(); - Node* pChild = firstChild(); - while (pChild) - { - static_cast<AbstractNode*>(pChild)->dispatchNodeRemovedFromDocument(); - pChild = pChild->nextSibling(); - } -} - - -void AbstractContainerNode::dispatchNodeInsertedIntoDocument() -{ - AbstractNode::dispatchNodeInsertedIntoDocument(); - Node* pChild = firstChild(); - while (pChild) - { - static_cast<AbstractNode*>(pChild)->dispatchNodeInsertedIntoDocument(); - pChild = pChild->nextSibling(); - } -} - - -bool AbstractContainerNode::hasChildNodes() const -{ - return _pFirstChild != 0; -} - - -bool AbstractContainerNode::hasAttributes() const -{ - return false; -} - - -Node* AbstractContainerNode::getNodeByPath(const XMLString& path) const -{ - XMLString::const_iterator it = path.begin(); - if (it != path.end() && *it == '/') - { - ++it; - if (it != path.end() && *it == '/') - { - ++it; - XMLString name; - while (it != path.end() && *it != '/' && *it != '@' && *it != '[') name += *it++; - if (it != path.end() && *it == '/') ++it; - if (name.empty()) name = WILDCARD; - AutoPtr<ElementsByTagNameList> pList = new ElementsByTagNameList(this, name); - unsigned long length = pList->length(); - for (unsigned long i = 0; i < length; i++) - { - XMLString::const_iterator beg = it; - const Node* pNode = findNode(beg, path.end(), pList->item(i), 0); - if (pNode) return const_cast<Node*>(pNode); - } - return 0; - } - } - return const_cast<Node*>(findNode(it, path.end(), this, 0)); -} - - -Node* AbstractContainerNode::getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const -{ - XMLString::const_iterator it = path.begin(); - if (it != path.end() && *it == '/') - { - ++it; - if (it != path.end() && *it == '/') - { - ++it; - XMLString name; - while (it != path.end() && *it != '/' && *it != '@' && *it != '[') name += *it++; - if (it != path.end() && *it == '/') ++it; - XMLString namespaceURI; - XMLString localName; - bool nameOK = true; - if (name.empty()) - { - namespaceURI = WILDCARD; - localName = WILDCARD; - } - else - { - nameOK = nsMap.processName(name, namespaceURI, localName, false); - } - if (nameOK) - { - AutoPtr<ElementsByTagNameListNS> pList = new ElementsByTagNameListNS(this, namespaceURI, localName); - unsigned long length = pList->length(); - for (unsigned long i = 0; i < length; i++) - { - XMLString::const_iterator beg = it; - const Node* pNode = findNode(beg, path.end(), pList->item(i), &nsMap); - if (pNode) return const_cast<Node*>(pNode); - } - } - return 0; - } - } - return const_cast<Node*>(findNode(it, path.end(), this, &nsMap)); -} - - -const Node* AbstractContainerNode::findNode(XMLString::const_iterator& it, const XMLString::const_iterator& end, const Node* pNode, const NSMap* pNSMap) -{ - if (pNode && it != end) - { - if (*it == '[') - { - ++it; - if (it != end && *it == '@') - { - ++it; - XMLString attr; - while (it != end && *it != ']' && *it != '=') attr += *it++; - if (it != end && *it == '=') - { - ++it; - XMLString value; - if (it != end && *it == '\'') - { - ++it; - while (it != end && *it != '\'') value += *it++; - if (it != end) ++it; - } - else - { - while (it != end && *it != ']') value += *it++; - } - if (it != end) ++it; - return findNode(it, end, findElement(attr, value, pNode, pNSMap), pNSMap); - } - else - { - if (it != end) ++it; - return findAttribute(attr, pNode, pNSMap); - } - } - else - { - XMLString index; - while (it != end && *it != ']') index += *it++; - if (it != end) ++it; -#ifdef XML_UNICODE_WCHAR_T - std::string idx; - Poco::UnicodeConverter::convert(index, idx); - int i = Poco::NumberParser::parse(idx); -#else - int i = Poco::NumberParser::parse(index); -#endif - return findNode(it, end, findElement(i, pNode, pNSMap), pNSMap); - } - } - else - { - while (it != end && *it == '/') ++it; - XMLString key; - while (it != end && *it != '/' && *it != '[') key += *it++; - - XMLString::const_iterator itStart(it); - const Node* pFound = 0; - const Node* pElem = findElement(key, pNode->firstChild(), pNSMap); - while (!pFound && pElem) - { - pFound = findNode(it, end, pElem, pNSMap); - if (!pFound) pElem = findElement(key, pElem->nextSibling(), pNSMap); - it = itStart; - } - return pFound; - } - } - else return pNode; -} - - -const Node* AbstractContainerNode::findElement(const XMLString& name, const Node* pNode, const NSMap* pNSMap) -{ - while (pNode) - { - if (pNode->nodeType() == Node::ELEMENT_NODE && namesAreEqual(pNode, name, pNSMap)) - return pNode; - pNode = pNode->nextSibling(); - } - return 0; -} - - -const Node* AbstractContainerNode::findElement(int index, const Node* pNode, const NSMap* pNSMap) -{ - const Node* pRefNode = pNode; - if (index > 0) - { - pNode = pNode->nextSibling(); - while (pNode) - { - if (namesAreEqual(pNode, pRefNode, pNSMap)) - { - if (--index == 0) break; - } - pNode = pNode->nextSibling(); - } - } - return pNode; -} - - -const Node* AbstractContainerNode::findElement(const XMLString& attr, const XMLString& value, const Node* pNode, const NSMap* pNSMap) -{ - const Node* pRefNode = pNode; - const Element* pElem = dynamic_cast<const Element*>(pNode); - if (!(pElem && pElem->hasAttributeValue(attr, value, pNSMap))) - { - pNode = pNode->nextSibling(); - while (pNode) - { - if (namesAreEqual(pNode, pRefNode, pNSMap)) - { - pElem = dynamic_cast<const Element*>(pNode); - if (pElem && pElem->hasAttributeValue(attr, value, pNSMap)) break; - } - pNode = pNode->nextSibling(); - } - } - return pNode; -} - - -const Attr* AbstractContainerNode::findAttribute(const XMLString& name, const Node* pNode, const NSMap* pNSMap) -{ - const Attr* pResult(0); - const Element* pElem = dynamic_cast<const Element*>(pNode); - if (pElem) - { - if (pNSMap) - { - XMLString namespaceURI; - XMLString localName; - if (pNSMap->processName(name, namespaceURI, localName, true)) - { - pResult = pElem->getAttributeNodeNS(namespaceURI, localName); - } - } - else - { - pResult = pElem->getAttributeNode(name); - } - } - return pResult; -} - - -bool AbstractContainerNode::hasAttributeValue(const XMLString& name, const XMLString& value, const NSMap* pNSMap) const -{ - const Attr* pAttr = findAttribute(name, this, pNSMap); - return pAttr && pAttr->getValue() == value; -} - - -bool AbstractContainerNode::namesAreEqual(const Node* pNode1, const Node* pNode2, const NSMap* pNSMap) -{ - if (pNSMap) - { - return pNode1->localName() == pNode2->localName() && pNode1->namespaceURI() == pNode2->namespaceURI(); - } - else - { - return pNode1->nodeName() == pNode2->nodeName(); - } -} - - -bool AbstractContainerNode::namesAreEqual(const Node* pNode, const XMLString& name, const NSMap* pNSMap) -{ - if (pNSMap) - { - XMLString namespaceURI; - XMLString localName; - if (name == WILDCARD) - { - return true; - } - else if (pNSMap->processName(name, namespaceURI, localName, false)) - { - return (pNode->namespaceURI() == namespaceURI || namespaceURI == WILDCARD) && (pNode->localName() == localName || localName == WILDCARD); - } - else return false; - } - else - { - return pNode->nodeName() == name || name == WILDCARD; - } -} - - -} } // namespace Poco::XML +// +// AbstractContainerNode.cpp +// +// Library: XML +// Package: DOM +// Module: DOM +// +// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. +// and Contributors. +// +// SPDX-License-Identifier: BSL-1.0 +// + + +#include "Poco/DOM/AbstractContainerNode.h" +#include "Poco/DOM/Document.h" +#include "Poco/DOM/Element.h" +#include "Poco/DOM/Attr.h" +#include "Poco/DOM/DOMException.h" +#include "Poco/DOM/ElementsByTagNameList.h" +#include "Poco/DOM/AutoPtr.h" +#include "Poco/NumberParser.h" +#include "Poco/UnicodeConverter.h" + + +namespace Poco { +namespace XML { + + +const XMLString AbstractContainerNode::WILDCARD(toXMLString("*")); + + +AbstractContainerNode::AbstractContainerNode(Document* pOwnerDocument): + AbstractNode(pOwnerDocument), + _pFirstChild(0) +{ +} + + +AbstractContainerNode::AbstractContainerNode(Document* pOwnerDocument, const AbstractContainerNode& node): + AbstractNode(pOwnerDocument, node), + _pFirstChild(0) +{ +} + + +AbstractContainerNode::~AbstractContainerNode() +{ + AbstractNode* pChild = static_cast<AbstractNode*>(_pFirstChild); + while (pChild) + { + AbstractNode* pDelNode = pChild; + pChild = pChild->_pNext; + pDelNode->_pNext = 0; + pDelNode->_pParent = 0; + pDelNode->release(); + } +} + + +Node* AbstractContainerNode::firstChild() const +{ + return _pFirstChild; +} + + +Node* AbstractContainerNode::lastChild() const +{ + AbstractNode* pChild = _pFirstChild; + if (pChild) + { + while (pChild->_pNext) pChild = pChild->_pNext; + return pChild; + } + return 0; +} + + +Node* AbstractContainerNode::insertBefore(Node* newChild, Node* refChild) +{ + poco_check_ptr (newChild); + + if (static_cast<AbstractNode*>(newChild)->_pOwner != _pOwner && static_cast<AbstractNode*>(newChild)->_pOwner != this) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR); + if (refChild && static_cast<AbstractNode*>(refChild)->_pParent != this) + throw DOMException(DOMException::NOT_FOUND_ERR); + if (newChild == refChild) + return newChild; + if (this == newChild) + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); + + AbstractNode* pFirst = 0; + AbstractNode* pLast = 0; + if (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) + { + AbstractContainerNode* pFrag = static_cast<AbstractContainerNode*>(newChild); + pFirst = pFrag->_pFirstChild; + pLast = pFirst; + if (pFirst) + { + while (pLast->_pNext) + { + pLast->_pParent = this; + pLast = pLast->_pNext; + } + pLast->_pParent = this; + } + pFrag->_pFirstChild = 0; + } + else + { + newChild->duplicate(); + AbstractContainerNode* pParent = static_cast<AbstractNode*>(newChild)->_pParent; + if (pParent) pParent->removeChild(newChild); + pFirst = static_cast<AbstractNode*>(newChild); + pLast = pFirst; + pFirst->_pParent = this; + } + if (_pFirstChild && pFirst) + { + AbstractNode* pCur = _pFirstChild; + if (pCur == refChild) + { + pLast->_pNext = _pFirstChild; + _pFirstChild = pFirst; + } + else + { + while (pCur && pCur->_pNext != refChild) pCur = pCur->_pNext; + if (pCur) + { + pLast->_pNext = pCur->_pNext; + pCur->_pNext = pFirst; + } + else throw DOMException(DOMException::NOT_FOUND_ERR); + } + } + else _pFirstChild = pFirst; + + if (events()) + { + while (pFirst && pFirst != pLast->_pNext) + { + pFirst->dispatchNodeInserted(); + pFirst->dispatchNodeInsertedIntoDocument(); + pFirst = pFirst->_pNext; + } + dispatchSubtreeModified(); + } + return newChild; +} + + +Node* AbstractContainerNode::replaceChild(Node* newChild, Node* oldChild) +{ + poco_check_ptr (newChild); + poco_check_ptr (oldChild); + + if (static_cast<AbstractNode*>(newChild)->_pOwner != _pOwner && static_cast<AbstractNode*>(newChild)->_pOwner != this) + throw DOMException(DOMException::WRONG_DOCUMENT_ERR); + if (static_cast<AbstractNode*>(oldChild)->_pParent != this) + throw DOMException(DOMException::NOT_FOUND_ERR); + if (newChild == oldChild) + return newChild; + if (this == newChild) + throw DOMException(DOMException::HIERARCHY_REQUEST_ERR); + + bool doEvents = events(); + if (newChild->nodeType() == Node::DOCUMENT_FRAGMENT_NODE) + { + insertBefore(newChild, oldChild); + removeChild(oldChild); + } + else + { + AbstractContainerNode* pParent = static_cast<AbstractNode*>(newChild)->_pParent; + if (pParent) pParent->removeChild(newChild); + + if (oldChild == _pFirstChild) + { + if (doEvents) + { + _pFirstChild->dispatchNodeRemoved(); + _pFirstChild->dispatchNodeRemovedFromDocument(); + } + static_cast<AbstractNode*>(newChild)->_pNext = static_cast<AbstractNode*>(oldChild)->_pNext; + static_cast<AbstractNode*>(newChild)->_pParent = this; + _pFirstChild->_pNext = 0; + _pFirstChild->_pParent = 0; + _pFirstChild = static_cast<AbstractNode*>(newChild); + if (doEvents) + { + static_cast<AbstractNode*>(newChild)->dispatchNodeInserted(); + static_cast<AbstractNode*>(newChild)->dispatchNodeInsertedIntoDocument(); + } + } + else + { + AbstractNode* pCur = _pFirstChild; + while (pCur && pCur->_pNext != oldChild) pCur = pCur->_pNext; + if (pCur) + { + poco_assert_dbg (pCur->_pNext == oldChild); + + if (doEvents) + { + static_cast<AbstractNode*>(oldChild)->dispatchNodeRemoved(); + static_cast<AbstractNode*>(oldChild)->dispatchNodeRemovedFromDocument(); + } + static_cast<AbstractNode*>(newChild)->_pNext = static_cast<AbstractNode*>(oldChild)->_pNext; + static_cast<AbstractNode*>(newChild)->_pParent = this; + static_cast<AbstractNode*>(oldChild)->_pNext = 0; + static_cast<AbstractNode*>(oldChild)->_pParent = 0; + pCur->_pNext = static_cast<AbstractNode*>(newChild); + if (doEvents) + { + static_cast<AbstractNode*>(newChild)->dispatchNodeInserted(); + static_cast<AbstractNode*>(newChild)->dispatchNodeInsertedIntoDocument(); + } + } + else throw DOMException(DOMException::NOT_FOUND_ERR); + } + newChild->duplicate(); + oldChild->autoRelease(); + } + if (doEvents) dispatchSubtreeModified(); + return oldChild; +} + + +Node* AbstractContainerNode::removeChild(Node* oldChild) +{ + poco_check_ptr (oldChild); + + bool doEvents = events(); + if (oldChild == _pFirstChild) + { + if (doEvents) + { + static_cast<AbstractNode*>(oldChild)->dispatchNodeRemoved(); + static_cast<AbstractNode*>(oldChild)->dispatchNodeRemovedFromDocument(); + } + _pFirstChild = _pFirstChild->_pNext; + static_cast<AbstractNode*>(oldChild)->_pNext = 0; + static_cast<AbstractNode*>(oldChild)->_pParent = 0; + } + else + { + AbstractNode* pCur = _pFirstChild; + while (pCur && pCur->_pNext != oldChild) pCur = pCur->_pNext; + if (pCur) + { + if (doEvents) + { + static_cast<AbstractNode*>(oldChild)->dispatchNodeRemoved(); + static_cast<AbstractNode*>(oldChild)->dispatchNodeRemovedFromDocument(); + } + pCur->_pNext = pCur->_pNext->_pNext; + static_cast<AbstractNode*>(oldChild)->_pNext = 0; + static_cast<AbstractNode*>(oldChild)->_pParent = 0; + } + else throw DOMException(DOMException::NOT_FOUND_ERR); + } + oldChild->autoRelease(); + if (doEvents) dispatchSubtreeModified(); + return oldChild; +} + + +Node* AbstractContainerNode::appendChild(Node* newChild) +{ + return insertBefore(newChild, 0); +} + + +void AbstractContainerNode::dispatchNodeRemovedFromDocument() +{ + AbstractNode::dispatchNodeRemovedFromDocument(); + Node* pChild = firstChild(); + while (pChild) + { + static_cast<AbstractNode*>(pChild)->dispatchNodeRemovedFromDocument(); + pChild = pChild->nextSibling(); + } +} + + +void AbstractContainerNode::dispatchNodeInsertedIntoDocument() +{ + AbstractNode::dispatchNodeInsertedIntoDocument(); + Node* pChild = firstChild(); + while (pChild) + { + static_cast<AbstractNode*>(pChild)->dispatchNodeInsertedIntoDocument(); + pChild = pChild->nextSibling(); + } +} + + +bool AbstractContainerNode::hasChildNodes() const +{ + return _pFirstChild != 0; +} + + +bool AbstractContainerNode::hasAttributes() const +{ + return false; +} + + +Node* AbstractContainerNode::getNodeByPath(const XMLString& path) const +{ + XMLString::const_iterator it = path.begin(); + if (it != path.end() && *it == '/') + { + ++it; + if (it != path.end() && *it == '/') + { + ++it; + XMLString name; + while (it != path.end() && *it != '/' && *it != '@' && *it != '[') name += *it++; + if (it != path.end() && *it == '/') ++it; + if (name.empty()) name = WILDCARD; + AutoPtr<ElementsByTagNameList> pList = new ElementsByTagNameList(this, name); + unsigned long length = pList->length(); + for (unsigned long i = 0; i < length; i++) + { + XMLString::const_iterator beg = it; + const Node* pNode = findNode(beg, path.end(), pList->item(i), 0); + if (pNode) return const_cast<Node*>(pNode); + } + return 0; + } + } + return const_cast<Node*>(findNode(it, path.end(), this, 0)); +} + + +Node* AbstractContainerNode::getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const +{ + XMLString::const_iterator it = path.begin(); + if (it != path.end() && *it == '/') + { + ++it; + if (it != path.end() && *it == '/') + { + ++it; + XMLString name; + while (it != path.end() && *it != '/' && *it != '@' && *it != '[') name += *it++; + if (it != path.end() && *it == '/') ++it; + XMLString namespaceURI; + XMLString localName; + bool nameOK = true; + if (name.empty()) + { + namespaceURI = WILDCARD; + localName = WILDCARD; + } + else + { + nameOK = nsMap.processName(name, namespaceURI, localName, false); + } + if (nameOK) + { + AutoPtr<ElementsByTagNameListNS> pList = new ElementsByTagNameListNS(this, namespaceURI, localName); + unsigned long length = pList->length(); + for (unsigned long i = 0; i < length; i++) + { + XMLString::const_iterator beg = it; + const Node* pNode = findNode(beg, path.end(), pList->item(i), &nsMap); + if (pNode) return const_cast<Node*>(pNode); + } + } + return 0; + } + } + return const_cast<Node*>(findNode(it, path.end(), this, &nsMap)); +} + + +const Node* AbstractContainerNode::findNode(XMLString::const_iterator& it, const XMLString::const_iterator& end, const Node* pNode, const NSMap* pNSMap) +{ + if (pNode && it != end) + { + if (*it == '[') + { + ++it; + if (it != end && *it == '@') + { + ++it; + XMLString attr; + while (it != end && *it != ']' && *it != '=') attr += *it++; + if (it != end && *it == '=') + { + ++it; + XMLString value; + if (it != end && *it == '\'') + { + ++it; + while (it != end && *it != '\'') value += *it++; + if (it != end) ++it; + } + else + { + while (it != end && *it != ']') value += *it++; + } + if (it != end) ++it; + return findNode(it, end, findElement(attr, value, pNode, pNSMap), pNSMap); + } + else + { + if (it != end) ++it; + return findAttribute(attr, pNode, pNSMap); + } + } + else + { + XMLString index; + while (it != end && *it != ']') index += *it++; + if (it != end) ++it; +#ifdef XML_UNICODE_WCHAR_T + std::string idx; + Poco::UnicodeConverter::convert(index, idx); + int i = Poco::NumberParser::parse(idx); +#else + int i = Poco::NumberParser::parse(index); +#endif + return findNode(it, end, findElement(i, pNode, pNSMap), pNSMap); + } + } + else + { + while (it != end && *it == '/') ++it; + XMLString key; + while (it != end && *it != '/' && *it != '[') key += *it++; + + XMLString::const_iterator itStart(it); + const Node* pFound = 0; + const Node* pElem = findElement(key, pNode->firstChild(), pNSMap); + while (!pFound && pElem) + { + pFound = findNode(it, end, pElem, pNSMap); + if (!pFound) pElem = findElement(key, pElem->nextSibling(), pNSMap); + it = itStart; + } + return pFound; + } + } + else return pNode; +} + + +const Node* AbstractContainerNode::findElement(const XMLString& name, const Node* pNode, const NSMap* pNSMap) +{ + while (pNode) + { + if (pNode->nodeType() == Node::ELEMENT_NODE && namesAreEqual(pNode, name, pNSMap)) + return pNode; + pNode = pNode->nextSibling(); + } + return 0; +} + + +const Node* AbstractContainerNode::findElement(int index, const Node* pNode, const NSMap* pNSMap) +{ + const Node* pRefNode = pNode; + if (index > 0) + { + pNode = pNode->nextSibling(); + while (pNode) + { + if (namesAreEqual(pNode, pRefNode, pNSMap)) + { + if (--index == 0) break; + } + pNode = pNode->nextSibling(); + } + } + return pNode; +} + + +const Node* AbstractContainerNode::findElement(const XMLString& attr, const XMLString& value, const Node* pNode, const NSMap* pNSMap) +{ + const Node* pRefNode = pNode; + const Element* pElem = dynamic_cast<const Element*>(pNode); + if (!(pElem && pElem->hasAttributeValue(attr, value, pNSMap))) + { + pNode = pNode->nextSibling(); + while (pNode) + { + if (namesAreEqual(pNode, pRefNode, pNSMap)) + { + pElem = dynamic_cast<const Element*>(pNode); + if (pElem && pElem->hasAttributeValue(attr, value, pNSMap)) break; + } + pNode = pNode->nextSibling(); + } + } + return pNode; +} + + +const Attr* AbstractContainerNode::findAttribute(const XMLString& name, const Node* pNode, const NSMap* pNSMap) +{ + const Attr* pResult(0); + const Element* pElem = dynamic_cast<const Element*>(pNode); + if (pElem) + { + if (pNSMap) + { + XMLString namespaceURI; + XMLString localName; + if (pNSMap->processName(name, namespaceURI, localName, true)) + { + pResult = pElem->getAttributeNodeNS(namespaceURI, localName); + } + } + else + { + pResult = pElem->getAttributeNode(name); + } + } + return pResult; +} + + +bool AbstractContainerNode::hasAttributeValue(const XMLString& name, const XMLString& value, const NSMap* pNSMap) const +{ + const Attr* pAttr = findAttribute(name, this, pNSMap); + return pAttr && pAttr->getValue() == value; +} + + +bool AbstractContainerNode::namesAreEqual(const Node* pNode1, const Node* pNode2, const NSMap* pNSMap) +{ + if (pNSMap) + { + return pNode1->localName() == pNode2->localName() && pNode1->namespaceURI() == pNode2->namespaceURI(); + } + else + { + return pNode1->nodeName() == pNode2->nodeName(); + } +} + + +bool AbstractContainerNode::namesAreEqual(const Node* pNode, const XMLString& name, const NSMap* pNSMap) +{ + if (pNSMap) + { + XMLString namespaceURI; + XMLString localName; + if (name == WILDCARD) + { + return true; + } + else if (pNSMap->processName(name, namespaceURI, localName, false)) + { + return (pNode->namespaceURI() == namespaceURI || namespaceURI == WILDCARD) && (pNode->localName() == localName || localName == WILDCARD); + } + else return false; + } + else + { + return pNode->nodeName() == name || name == WILDCARD; + } +} + + +} } // namespace Poco::XML |