SF# 3178109

This commit is contained in:
Guenter Obiltschnig
2011-08-22 09:45:56 +00:00
parent 885c9547f4
commit 1675ba8d1c
14 changed files with 461 additions and 350 deletions

View File

@@ -99,6 +99,13 @@ Release 1.4.2 (2011-08-xx)
one delegate for each event has been removed. For most cases, dispatching
events should be faster, as dispatching an event now needs less dynamic memory
allocations.
- fixed SF# 3178109: getNodeByPath() changes:
getNodeByPath() and getNodeByPathNS() have been moved to Poco::XML::Node.
Furthermore, when invoked on a Poco::XML::Document, the behavior has changed
so that the document element is now included when traversing the path (previously,
traversal would start at the document element, now it starts at the document).
The path expression can now start with a double-slash, which results in a recursive
search for the path's first element in the DOM tree.
Release 1.4.1p1 (2011-02-08)
@@ -1572,4 +1579,4 @@ building the libraries.
--
$Id: //poco/1.4/dist/CHANGELOG#26 $
$Id: //poco/1.4/dist/CHANGELOG#27 $

View File

@@ -1,7 +1,7 @@
//
// AbstractContainerNode.h
//
// $Id: //poco/1.4/XML/include/Poco/DOM/AbstractContainerNode.h#1 $
// $Id: //poco/1.4/XML/include/Poco/DOM/AbstractContainerNode.h#2 $
//
// Library: XML
// Package: DOM
@@ -64,6 +64,8 @@ public:
Node* appendChild(Node* newChild);
bool hasChildNodes() const;
bool hasAttributes() const;
Node* getNodeByPath(const XMLString& path) const;
Node* getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const;
protected:
AbstractContainerNode(Document* pOwnerDocument);
@@ -72,6 +74,15 @@ protected:
void dispatchNodeRemovedFromDocument();
void dispatchNodeInsertedIntoDocument();
static const Node* findNode(XMLString::const_iterator& it, const XMLString::const_iterator& end, const Node* pNode, const NSMap* pNSMap);
static const Node* findElement(const XMLString& name, const Node* pNode, const NSMap* pNSMap);
static const Node* findElement(int index, const Node* pNode, const NSMap* pNSMap);
static const Node* findElement(const XMLString& attr, const XMLString& value, const Node* pNode, const NSMap* pNSMap);
static const Attr* findAttribute(const XMLString& name, const Node* pNode, const NSMap* pNSMap);
bool hasAttributeValue(const XMLString& name, const XMLString& value, const NSMap* pNSMap) const;
static bool namesAreEqual(const Node* pNode1, const Node* pNode2, const NSMap* pNSMap);
static bool namesAreEqual(const Node* pNode, const XMLString& name, const NSMap* pNSMap);
private:
AbstractNode* _pFirstChild;

View File

@@ -1,7 +1,7 @@
//
// AbstractNode.h
//
// $Id: //poco/1.4/XML/include/Poco/DOM/AbstractNode.h#1 $
// $Id: //poco/1.4/XML/include/Poco/DOM/AbstractNode.h#2 $
//
// Library: XML
// Package: DOM
@@ -93,6 +93,8 @@ public:
// Extensions
XMLString innerText() const;
Node* getNodeByPath(const XMLString& path) const;
Node* getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const;
virtual void autoRelease();

View File

@@ -1,7 +1,7 @@
//
// Document.h
//
// $Id: //poco/1.4/XML/include/Poco/DOM/Document.h#1 $
// $Id: //poco/1.4/XML/include/Poco/DOM/Document.h#2 $
//
// Library: XML
// Package: DOM
@@ -246,48 +246,6 @@ public:
///
/// This method is an extension to the W3C Document Object Model.
Node* getNodeByPath(const XMLString& path);
/// Searches a node (element or attribute) based on a simplified XPath
/// expression.
///
/// Only simple XPath expressions are supported. These are the slash
/// notation for specifying paths to elements, and the square bracket
/// expression for finding elements by their index, by attribute value,
/// or finding attributes by names.
///
/// The slash at the beginning is optional, the evaluation always starts
/// at the document element.
///
/// Examples:
/// /elem1/elem2/elem3
/// /elem1/elem2[1]
/// /elem1/elem2[@attr1]
/// /elem1/elem2[@attr1='value']
///
/// This method is an extension to the W3C Document Object Model.
Node* getNodeByPathNS(const XMLString& path, const Element::NSMap& nsMap);
/// Searches a node (element or attribute) based on a simplified XPath
/// expression. The given NSMap must contain mappings from namespace
/// prefixes to namespace URIs for all namespace prefixes used in
/// the path expression.
///
/// Only simple XPath expressions are supported. These are the slash
/// notation for specifying paths to elements, and the square bracket
/// expression for finding elements by their index, by attribute value,
/// or finding attributes by names.
///
/// The slash at the beginning is optional, the evaluation always starts
/// at the document element.
///
/// Examples:
/// /ns1:elem1/ns2:elem2/ns2:elem3
/// /ns1:elem1/ns2:elem2[1]
/// /ns1:elem1/ns2:elem2[@attr1]
/// /ns1:elem1/ns2:elem2[@attr1='value']
///
/// This method is an extension to the W3C Document Object Model.
protected:
~Document();

View File

@@ -1,7 +1,7 @@
//
// Element.h
//
// $Id: //poco/1.4/XML/include/Poco/DOM/Element.h#1 $
// $Id: //poco/1.4/XML/include/Poco/DOM/Element.h#2 $
//
// Library: XML
// Package: DOM
@@ -43,7 +43,6 @@
#include "Poco/XML/XML.h"
#include "Poco/DOM/AbstractContainerNode.h"
#include "Poco/XML/Name.h"
#include "Poco/SAX/NamespaceSupport.h"
namespace Poco {
@@ -176,10 +175,6 @@ public:
XMLString prefix() const;
const XMLString& localName() const;
bool hasAttributes() const;
// Non-standard extensions
typedef Poco::XML::NamespaceSupport NSMap;
XMLString innerText() const;
Element* getChildElement(const XMLString& name) const;
@@ -205,49 +200,7 @@ public:
/// has the given elementId. If no such element exists, returns null.
///
/// This method is an extension to the W3C Document Object Model.
Node* getNodeByPath(const XMLString& path);
/// Searches a node (element or attribute) based on a simplified XPath
/// expression.
///
/// Only simple XPath expressions are supported. These are the slash
/// notation for specifying paths to elements, and the square bracket
/// expression for finding elements by their index, by attribute value,
/// or finding attributes by names.
///
/// The slash at the beginning is optional, the evaluation always starts
/// at this element.
///
/// Examples:
/// /elem1/elem2/elem3
/// /elem1/elem2[1]
/// /elem1/elem2[@attr1]
/// /elem1/elem2[@attr1='value']
///
/// This method is an extension to the W3C Document Object Model.
Node* getNodeByPathNS(const XMLString& path, const NSMap& nsMap);
/// Searches a node (element or attribute) based on a simplified XPath
/// expression. The given NSMap must contain mappings from namespace
/// prefixes to namespace URIs for all namespace prefixes used in
/// the path expression.
///
/// Only simple XPath expressions are supported. These are the slash
/// notation for specifying paths to elements, and the square bracket
/// expression for finding elements by their index, by attribute value,
/// or finding attributes by names.
///
/// The slash at the beginning is optional, the evaluation always starts
/// at this element.
///
/// Examples:
/// /ns1:elem1/ns2:elem2/ns2:elem3
/// /ns1:elem1/ns2:elem2[1]
/// /ns1:elem1/ns2:elem2[@attr1]
/// /ns1:elem1/ns2:elem2[@attr1='value']
///
/// This method is an extension to the W3C Document Object Model.
// Node
const XMLString& nodeName() const;
NamedNodeMap* attributes() const;
@@ -262,15 +215,6 @@ protected:
void dispatchNodeRemovedFromDocument();
void dispatchNodeInsertedIntoDocument();
static Node* findNode(XMLString::const_iterator& it, const XMLString::const_iterator& end, Node* pNode, const NSMap* pNSMap);
static Node* findElement(const XMLString& name, Node* pNode, const NSMap* pNSMap);
static Node* findElement(int index, Node* pNode, const NSMap* pNSMap);
static Node* findElement(const XMLString& attr, const XMLString& value, Node* pNode, const NSMap* pNSMap);
static Attr* findAttribute(const XMLString& name, Node* pNode, const NSMap* pNSMap);
bool hasAttributeValue(const XMLString& name, const XMLString& value, const NSMap* pNSMap);
static bool namesAreEqual(Node* pNode1, Node* pNode2, const NSMap* pNSMap);
static bool namesAreEqual(Node* pNode, const XMLString& name, const NSMap* pNSMap);
private:
const Name& _name;

View File

@@ -1,7 +1,7 @@
//
// ElementsByTagNameList.h
//
// $Id: //poco/1.4/XML/include/Poco/DOM/ElementsByTagNameList.h#1 $
// $Id: //poco/1.4/XML/include/Poco/DOM/ElementsByTagNameList.h#2 $
//
// Library: XML
// Package: DOM
@@ -69,6 +69,7 @@ protected:
XMLString _name;
mutable unsigned long _count;
friend class AbstractContainerNode;
friend class Element;
friend class Document;
};
@@ -95,6 +96,7 @@ protected:
XMLString _namespaceURI;
mutable unsigned long _count;
friend class AbstractContainerNode;
friend class Element;
friend class Document;
};

View File

@@ -1,7 +1,7 @@
//
// Node.h
//
// $Id: //poco/1.4/XML/include/Poco/DOM/Node.h#1 $
// $Id: //poco/1.4/XML/include/Poco/DOM/Node.h#2 $
//
// Library: XML
// Package: DOM
@@ -43,6 +43,7 @@
#include "Poco/XML/XML.h"
#include "Poco/DOM/EventTarget.h"
#include "Poco/XML/XMLString.h"
#include "Poco/SAX/NamespaceSupport.h"
namespace Poco {
@@ -229,11 +230,62 @@ public:
/// Returns whether this node (if it is an element) has any attributes.
// Extensions
typedef Poco::XML::NamespaceSupport NSMap;
virtual XMLString innerText() const = 0;
/// Returns a string containing the concatenated values of the node
/// and all its child nodes.
///
/// This method is not part of the W3C Document Object Model.
virtual Node* getNodeByPath(const XMLString& path) const = 0;
/// Searches a node (element or attribute) based on a simplified XPath
/// expression.
///
/// Only simple XPath expressions are supported. These are the slash
/// notation for specifying paths to elements, and the square bracket
/// expression for finding elements by their index, by attribute value,
/// or finding attributes by names.
///
/// The slash at the beginning is optional, the evaluation always starts
/// at this element. A double-slash at the beginning recursively searches
/// the entire subtree for the first element.
///
/// Examples:
/// elem1/elem2/elem3
/// /elem1/elem2/elem3
/// /elem1/elem2[1]
/// /elem1/elem2[@attr1]
/// /elem1/elem2[@attr1='value']
/// //elem2[@attr1='value']
/// //[@attr1='value']
///
/// This method is an extension to the W3C Document Object Model.
virtual Node* getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const = 0;
/// Searches a node (element or attribute) based on a simplified XPath
/// expression. The given NSMap must contain mappings from namespace
/// prefixes to namespace URIs for all namespace prefixes used in
/// the path expression.
///
/// Only simple XPath expressions are supported. These are the slash
/// notation for specifying paths to elements, and the square bracket
/// expression for finding elements by their index, by attribute value,
/// or finding attributes by names.
///
/// The slash at the beginning is optional, the evaluation always starts
/// at this element. A double-slash at the beginning recursively searches
/// the entire subtree for the first element.
///
/// Examples:
/// /ns1:elem1/ns2:elem2/ns2:elem3
/// /ns1:elem1/ns2:elem2[1]
/// /ns1:elem1/ns2:elem2[@attr1]
/// /ns1:elem1/ns2:elem2[@attr1='value']
/// //ns2:elem2[@ns1:attr1='value']
/// //[@ns1:attr1='value']
///
/// This method is an extension to the W3C Document Object Model.
protected:
virtual ~Node();

View File

@@ -1,7 +1,7 @@
//
// AbstractContainerNode.cpp
//
// $Id: //poco/1.4/XML/src/AbstractContainerNode.cpp#1 $
// $Id: //poco/1.4/XML/src/AbstractContainerNode.cpp#2 $
//
// Library: XML
// Package: DOM
@@ -36,7 +36,12 @@
#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"
namespace Poco {
@@ -322,4 +327,245 @@ bool AbstractContainerNode::hasAttributes() const
}
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 += '*';
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 += '*';
localName += '*';
}
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;
return findNode(it, end, findElement(Poco::NumberParser::parse(index), pNode, pNSMap), pNSMap);
}
}
else
{
while (it != end && *it == '/') ++it;
XMLString key;
while (it != end && *it != '/' && *it != '[') key += *it++;
return findNode(it, end, findElement(key, pNode, pNSMap), pNSMap);
}
}
else return pNode;
}
const Node* AbstractContainerNode::findElement(const XMLString& name, const Node* pNode, const NSMap* pNSMap)
{
Node* pChild = pNode->firstChild();
while (pChild)
{
if (pChild->nodeType() == Node::ELEMENT_NODE && namesAreEqual(pChild, name, pNSMap))
return pChild;
pChild = pChild->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 (pNSMap->processName(name, namespaceURI, localName, false))
{
return pNode->namespaceURI() == namespaceURI && pNode->localName() == localName;
}
else return false;
}
else
{
return pNode->nodeName() == name;
}
}
} } // namespace Poco::XML

View File

@@ -1,7 +1,7 @@
//
// AbstractNode.cpp
//
// $Id: //poco/1.4/XML/src/AbstractNode.cpp#1 $
// $Id: //poco/1.4/XML/src/AbstractNode.cpp#2 $
//
// Library: XML
// Package: DOM
@@ -237,6 +237,18 @@ XMLString AbstractNode::innerText() const
}
Node* AbstractNode::getNodeByPath(const XMLString& path) const
{
return 0;
}
Node* AbstractNode::getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const
{
return 0;
}
void AbstractNode::addEventListener(const XMLString& type, EventListener* listener, bool useCapture)
{
if (_pEventDispatcher)

View File

@@ -1,7 +1,7 @@
//
// Document.cpp
//
// $Id: //poco/1.4/XML/src/Document.cpp#1 $
// $Id: //poco/1.4/XML/src/Document.cpp#2 $
//
// Library: XML
// Package: DOM
@@ -322,24 +322,4 @@ Element* Document::getElementByIdNS(const XMLString& elementId, const XMLString&
}
Node* Document::getNodeByPath(const XMLString& path)
{
Element* pElem = documentElement();
if (pElem)
return pElem->getNodeByPath(path);
else
return 0;
}
Node* Document::getNodeByPathNS(const XMLString& path, const Element::NSMap& nsMap)
{
Element* pElem = documentElement();
if (pElem)
return pElem->getNodeByPathNS(path, nsMap);
else
return 0;
}
} } // namespace Poco::XML

View File

@@ -1,7 +1,7 @@
//
// Element.cpp
//
// $Id: //poco/1.4/XML/src/Element.cpp#1 $
// $Id: //poco/1.4/XML/src/Element.cpp#2 $
//
// Library: XML
// Package: DOM
@@ -41,7 +41,6 @@
#include "Poco/DOM/ElementsByTagNameList.h"
#include "Poco/DOM/Text.h"
#include "Poco/DOM/AttrMap.h"
#include "Poco/NumberParser.h"
namespace Poco {
@@ -464,191 +463,4 @@ Element* Element::getElementByIdNS(const XMLString& elementId, const XMLString&
}
Node* Element::getNodeByPath(const XMLString& path)
{
XMLString::const_iterator it = path.begin();
if (it != path.end() && *it == '/') ++it;
return findNode(it, path.end(), this, 0);
}
Node* Element::getNodeByPathNS(const XMLString& path, const NSMap& nsMap)
{
XMLString::const_iterator it = path.begin();
if (it != path.end() && *it == '/') ++it;
return findNode(it, path.end(), this, &nsMap);
}
Node* Element::findNode(XMLString::const_iterator& it, const XMLString::const_iterator& end, 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;
return findNode(it, end, findElement(Poco::NumberParser::parse(index), pNode, pNSMap), pNSMap);
}
}
else
{
while (it != end && *it == '/') ++it;
XMLString key;
while (it != end && *it != '/' && *it != '[') key += *it++;
return findNode(it, end, findElement(key, pNode, pNSMap), pNSMap);
}
}
else return pNode;
}
Node* Element::findElement(const XMLString& name, Node* pNode, const NSMap* pNSMap)
{
Node* pChild = pNode->firstChild();
while (pChild)
{
if (pChild->nodeType() == Node::ELEMENT_NODE && namesAreEqual(pChild, name, pNSMap))
return pChild;
pChild = pChild->nextSibling();
}
return 0;
}
Node* Element::findElement(int index, Node* pNode, const NSMap* pNSMap)
{
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;
}
Node* Element::findElement(const XMLString& attr, const XMLString& value, Node* pNode, const NSMap* pNSMap)
{
Node* pRefNode = pNode;
Element* pElem = dynamic_cast<Element*>(pNode);
if (!(pElem && pElem->hasAttributeValue(attr, value, pNSMap)))
{
pNode = pNode->nextSibling();
while (pNode)
{
if (namesAreEqual(pNode, pRefNode, pNSMap))
{
pElem = dynamic_cast<Element*>(pNode);
if (pElem && pElem->hasAttributeValue(attr, value, pNSMap)) break;
}
pNode = pNode->nextSibling();
}
}
return pNode;
}
Attr* Element::findAttribute(const XMLString& name, Node* pNode, const NSMap* pNSMap)
{
Attr* pResult(0);
Element* pElem = dynamic_cast<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 Element::hasAttributeValue(const XMLString& name, const XMLString& value, const NSMap* pNSMap)
{
Attr* pAttr = findAttribute(name, this, pNSMap);
return pAttr && pAttr->getValue() == value;
}
bool Element::namesAreEqual(Node* pNode1, Node* pNode2, const NSMap* pNSMap)
{
if (pNSMap)
{
return pNode1->localName() == pNode2->localName() && pNode1->namespaceURI() == pNode2->namespaceURI();
}
else
{
return pNode1->nodeName() == pNode2->nodeName();
}
}
bool Element::namesAreEqual(Node* pNode, const XMLString& name, const NSMap* pNSMap)
{
if (pNSMap)
{
XMLString namespaceURI;
XMLString localName;
if (pNSMap->processName(name, namespaceURI, localName, false))
{
return pNode->namespaceURI() == namespaceURI && pNode->localName() == localName;
}
else return false;
}
else
{
return pNode->nodeName() == name;
}
}
} } // namespace Poco::XML

View File

@@ -1,7 +1,7 @@
//
// XMLWriter.cpp
//
// $Id: //poco/1.4/XML/src/XMLWriter.cpp#2 $
// $Id: //poco/1.4/XML/src/XMLWriter.cpp#3 $
//
// Library: XML
// Package: XML
@@ -608,6 +608,9 @@ void XMLWriter::writeStartElement(const XMLString& namespaceURI, const XMLString
_namespaces.pushContext();
_nsContextPushed = false;
++_elementCount;
declareAttributeNamespaces(attributes);
writeMarkup(MARKUP_LT);
if (!localName.empty() && (qname.empty() || localName == qname))
{
@@ -639,7 +642,6 @@ void XMLWriter::writeStartElement(const XMLString& namespaceURI, const XMLString
}
else throw XMLException("Tag mismatch", nameToString(localName, qname));
declareAttributeNamespaces(attributes);
AttributeMap attributeMap;
addNamespaceAttributes(attributeMap);
addAttributes(attributeMap, attributes, namespaceURI);

View File

@@ -1,7 +1,7 @@
//
// ElementTest.cpp
//
// $Id: //poco/1.4/XML/testsuite/src/ElementTest.cpp#1 $
// $Id: //poco/1.4/XML/testsuite/src/ElementTest.cpp#2 $
//
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
@@ -632,6 +632,25 @@ void ElementTest::testChildElementNS()
void ElementTest::testNodeByPath()
{
/*
<root>
<elem1>
<elemA/>
<elemA/>
</elem1>
<elem2>
<elemB attr1="value1"/>
<elemB attr1="value2"/>
<elemB attr1="value3"/>
<elemC attr1="value1">
<elemC1 attr1="value1"/>
<elemC2/>
</elemC>
<elemC attr1="value2"/>
</elem2>
</root>
*/
AutoPtr<Document> pDoc = new Document;
AutoPtr<Element> pRoot = pDoc->createElement("root");
@@ -669,12 +688,17 @@ void ElementTest::testNodeByPath()
pRoot->appendChild(pElem1);
pRoot->appendChild(pElem2);
pDoc->appendChild(pRoot);
Node* pNode = pRoot->getNodeByPath("/");
assert (pNode == pRoot);
pNode = pRoot->getNodeByPath("/elem1");
assert (pNode == pElem1);
pNode = pDoc->getNodeByPath("/root/elem1");
assert (pNode == pElem1);
pNode = pRoot->getNodeByPath("/elem2");
assert (pNode == pElem2);
@@ -719,23 +743,59 @@ void ElementTest::testNodeByPath()
pNode = pRoot->getNodeByPath("/elem2/elemC[@attr1='value1']/elemC1[@attr1]");
assert (pNode && pNode->nodeValue() == "value1");
pNode = pDoc->getNodeByPath("//elemB[@attr1='value1']");
assert (pNode == pElem21);
pNode = pDoc->getNodeByPath("//elemB[@attr1='value2']");
assert (pNode == pElem22);
pNode = pDoc->getNodeByPath("//elemB[@attr1='value3']");
assert (pNode == pElem23);
pNode = pDoc->getNodeByPath("//elemB[@attr1='value4']");
assert (pNode == 0);
pNode = pDoc->getNodeByPath("//[@attr1='value1']");
assert (pNode == pElem21);
pNode = pDoc->getNodeByPath("//[@attr1='value2']");
assert (pNode == pElem22);
}
void ElementTest::testNodeByPathNS()
{
/*
<ns1:root xmlns:ns1="urn:ns1">
<ns1:elem1>
<ns2:elemA xmlns:ns2="urn:ns2"/>
<ns3:elemA xmlns:ns3="urn:ns2"/>
</ns1:elem1>
<ns1:elem2>
<ns2:elemB ns2:attr1="value1" xmlns:ns2="urn:ns2"/>
<ns2:elemB ns2:attr1="value2" xmlns:ns2="urn:ns2"/>
<ns2:elemB ns2:attr1="value3" xmlns:ns2="urn:ns2"/>
<ns2:elemC ns2:attr1="value1" xmlns:ns2="urn:ns2">
<ns2:elemC1 ns2:attr1="value1"/>
<ns2:elemC2/>
</ns2:elemC>
<ns2:elemC ns2:attr1="value2" xmlns:ns2="urn:ns2"/>
</ns1:elem2>
</ns1:root>
*/
AutoPtr<Document> pDoc = new Document;
AutoPtr<Element> pRoot = pDoc->createElementNS("urn:ns1", "root");
AutoPtr<Element> pElem1 = pDoc->createElementNS("urn:ns1", "elem1");
AutoPtr<Element> pElem11 = pDoc->createElementNS("urn:ns2", "elemA");
AutoPtr<Element> pElem12 = pDoc->createElementNS("urn:ns2", "elemA");
AutoPtr<Element> pElem2 = pDoc->createElementNS("urn:ns1", "elem2");
AutoPtr<Element> pElem21 = pDoc->createElementNS("urn:ns2", "elemB");
AutoPtr<Element> pElem22 = pDoc->createElementNS("urn:ns2", "elemB");
AutoPtr<Element> pElem23 = pDoc->createElementNS("urn:ns2", "elemB");
AutoPtr<Element> pElem24 = pDoc->createElementNS("urn:ns2", "elemC");
AutoPtr<Element> pElem25 = pDoc->createElementNS("urn:ns2", "elemC");
AutoPtr<Element> pRoot = pDoc->createElementNS("urn:ns1", "ns1:root");
AutoPtr<Element> pElem1 = pDoc->createElementNS("urn:ns1", "ns1:elem1");
AutoPtr<Element> pElem11 = pDoc->createElementNS("urn:ns2", "ns2:elemA");
AutoPtr<Element> pElem12 = pDoc->createElementNS("urn:ns2", "ns2:elemA");
AutoPtr<Element> pElem2 = pDoc->createElementNS("urn:ns1", "ns1:elem2");
AutoPtr<Element> pElem21 = pDoc->createElementNS("urn:ns2", "ns2:elemB");
AutoPtr<Element> pElem22 = pDoc->createElementNS("urn:ns2", "ns2:elemB");
AutoPtr<Element> pElem23 = pDoc->createElementNS("urn:ns2", "ns2:elemB");
AutoPtr<Element> pElem24 = pDoc->createElementNS("urn:ns2", "ns2:elemC");
AutoPtr<Element> pElem25 = pDoc->createElementNS("urn:ns2", "ns2:elemC");
pElem21->setAttributeNS("urn:ns2", "ns2:attr1", "value1");
pElem22->setAttributeNS("urn:ns2", "ns2:attr1", "value2");
@@ -760,64 +820,87 @@ void ElementTest::testNodeByPathNS()
pRoot->appendChild(pElem1);
pRoot->appendChild(pElem2);
pDoc->appendChild(pRoot);
Element::NSMap nsMap;
nsMap.declarePrefix("ns1", "urn:ns1");
nsMap.declarePrefix("ns2", "urn:ns2");
nsMap.declarePrefix("NS2", "urn:ns2");
Node* pNode = pRoot->getNodeByPathNS("/", nsMap);
assert (pNode == pRoot);
pNode = pRoot->getNodeByPathNS("/ns1:elem1", nsMap);
assert (pNode == pElem1);
pNode = pDoc->getNodeByPathNS("/ns1:root/ns1:elem1", nsMap);
assert (pNode == pElem1);
pNode = pRoot->getNodeByPathNS("/ns1:elem2", nsMap);
assert (pNode == pElem2);
pNode = pRoot->getNodeByPathNS("/ns1:elem1/ns2:elemA", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem1/NS2:elemA", nsMap);
assert (pNode == pElem11);
pNode = pRoot->getNodeByPathNS("/ns1:elem1/ns2:elemA[0]", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem1/NS2:elemA[0]", nsMap);
assert (pNode == pElem11);
pNode = pRoot->getNodeByPathNS("/ns1:elem1/ns2:elemA[1]", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem1/NS2:elemA[1]", nsMap);
assert (pNode == pElem12);
pNode = pRoot->getNodeByPathNS("/ns1:elem1/ns2:elemA[2]", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem1/NS2:elemA[2]", nsMap);
assert (pNode == 0);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/ns2:elemB", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB", nsMap);
assert (pNode == pElem21);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/ns2:elemB[0]", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[0]", nsMap);
assert (pNode == pElem21);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/ns2:elemB[1]", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[1]", nsMap);
assert (pNode == pElem22);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/ns2:elemB[2]", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[2]", nsMap);
assert (pNode == pElem23);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/ns2:elemB[3]", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[3]", nsMap);
assert (pNode == 0);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/ns2:elemB[@ns2:attr1]", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[@NS2:attr1]", nsMap);
assert (pNode && pNode->nodeValue() == "value1");
pNode = pRoot->getNodeByPathNS("/ns1:elem2/ns2:elemB[@ns2:attr2]", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[@NS2:attr2]", nsMap);
assert (pNode == 0);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/ns2:elemB[@ns2:attr1='value2']", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemB[@NS2:attr1='value2']", nsMap);
assert (pNode == pElem22);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/ns2:elemC[@ns2:attr1='value1']/ns2:elemC1", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemC[@NS2:attr1='value1']/NS2:elemC1", nsMap);
assert (pNode == pElem241);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/ns2:elemC[@ns2:attr1='value1']/ns2:elemC1[@ns2:attr1]", nsMap);
pNode = pRoot->getNodeByPathNS("/ns1:elem2/NS2:elemC[@NS2:attr1='value1']/NS2:elemC1[@NS2:attr1]", nsMap);
assert (pNode && pNode->nodeValue() == "value1");
pNode = pRoot->getNodeByPathNS("/ns2:elem1", nsMap);
pNode = pRoot->getNodeByPathNS("/NS2:elem1", nsMap);
assert (pNode == 0);
pNode = pDoc->getNodeByPathNS("//NS2:elemB[@NS2:attr1='value1']", nsMap);
assert (pNode == pElem21);
pNode = pDoc->getNodeByPathNS("//NS2:elemB[@NS2:attr1='value2']", nsMap);
assert (pNode == pElem22);
pNode = pDoc->getNodeByPathNS("//NS2:elemB[@NS2:attr1='value3']", nsMap);
assert (pNode == pElem23);
pNode = pDoc->getNodeByPathNS("//NS2:elemB[@NS2:attr1='value4']", nsMap);
assert (pNode == 0);
pNode = pDoc->getNodeByPathNS("//[@NS2:attr1='value1']", nsMap);
assert (pNode == pElem21);
pNode = pDoc->getNodeByPathNS("//[@NS2:attr1='value2']", nsMap);
assert (pNode == pElem22);
}

View File

@@ -1,7 +1,7 @@
//
// XMLWriterTest.cpp
//
// $Id: //poco/1.4/XML/testsuite/src/XMLWriterTest.cpp#2 $
// $Id: //poco/1.4/XML/testsuite/src/XMLWriterTest.cpp#3 $
//
// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
// and Contributors.
@@ -487,7 +487,7 @@ void XMLWriterTest::testAttributeNamespaces()
writer.endElement("urn:ns", "r", "");
writer.endDocument();
std::string xml = str.str();
assert (xml == "<ns1:r ns1:myattr2=\"attrValue2\" ns2:myattr=\"attrValue\" xmlns:ns1=\"urn:ns\" xmlns:ns2=\"urn:other\">data</ns1:r>");
assert (xml == "<ns2:r ns1:myattr=\"attrValue\" ns2:myattr2=\"attrValue2\" xmlns:ns1=\"urn:other\" xmlns:ns2=\"urn:ns\">data</ns2:r>");
}