mirror of
https://github.com/pocoproject/poco.git
synced 2025-04-16 06:56:41 +02:00
#3215: XML parser returns item from different element in a array
This commit is contained in:
parent
6fda5b590b
commit
73ee047a37
@ -53,7 +53,7 @@ protected:
|
|||||||
void dispatchNodeRemovedFromDocument();
|
void dispatchNodeRemovedFromDocument();
|
||||||
void dispatchNodeInsertedIntoDocument();
|
void dispatchNodeInsertedIntoDocument();
|
||||||
|
|
||||||
static const Node* findNode(XMLString::const_iterator& it, const XMLString::const_iterator& end, const Node* pNode, const NSMap* pNSMap);
|
static const Node* findNode(XMLString::const_iterator& it, const XMLString::const_iterator& end, const Node* pNode, const NSMap* pNSMap, bool& indexBound);
|
||||||
static const Node* findElement(const XMLString& name, 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(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 Node* findElement(const XMLString& attr, const XMLString& value, const Node* pNode, const NSMap* pNSMap);
|
||||||
|
@ -311,6 +311,7 @@ bool AbstractContainerNode::hasAttributes() const
|
|||||||
|
|
||||||
Node* AbstractContainerNode::getNodeByPath(const XMLString& path) const
|
Node* AbstractContainerNode::getNodeByPath(const XMLString& path) const
|
||||||
{
|
{
|
||||||
|
bool indexBound;
|
||||||
XMLString::const_iterator it = path.begin();
|
XMLString::const_iterator it = path.begin();
|
||||||
if (it != path.end() && *it == '/')
|
if (it != path.end() && *it == '/')
|
||||||
{
|
{
|
||||||
@ -327,18 +328,19 @@ Node* AbstractContainerNode::getNodeByPath(const XMLString& path) const
|
|||||||
for (unsigned long i = 0; i < length; i++)
|
for (unsigned long i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
XMLString::const_iterator beg = it;
|
XMLString::const_iterator beg = it;
|
||||||
const Node* pNode = findNode(beg, path.end(), pList->item(i), 0);
|
const Node* pNode = findNode(beg, path.end(), pList->item(i), 0, indexBound);
|
||||||
if (pNode) return const_cast<Node*>(pNode);
|
if (pNode) return const_cast<Node*>(pNode);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return const_cast<Node*>(findNode(it, path.end(), this, 0));
|
return const_cast<Node*>(findNode(it, path.end(), this, 0, indexBound));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Node* AbstractContainerNode::getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const
|
Node* AbstractContainerNode::getNodeByPathNS(const XMLString& path, const NSMap& nsMap) const
|
||||||
{
|
{
|
||||||
|
bool indexBound;
|
||||||
XMLString::const_iterator it = path.begin();
|
XMLString::const_iterator it = path.begin();
|
||||||
if (it != path.end() && *it == '/')
|
if (it != path.end() && *it == '/')
|
||||||
{
|
{
|
||||||
@ -368,19 +370,20 @@ Node* AbstractContainerNode::getNodeByPathNS(const XMLString& path, const NSMap&
|
|||||||
for (unsigned long i = 0; i < length; i++)
|
for (unsigned long i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
XMLString::const_iterator beg = it;
|
XMLString::const_iterator beg = it;
|
||||||
const Node* pNode = findNode(beg, path.end(), pList->item(i), &nsMap);
|
const Node* pNode = findNode(beg, path.end(), pList->item(i), &nsMap, indexBound);
|
||||||
if (pNode) return const_cast<Node*>(pNode);
|
if (pNode) return const_cast<Node*>(pNode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return const_cast<Node*>(findNode(it, path.end(), this, &nsMap));
|
return const_cast<Node*>(findNode(it, path.end(), this, &nsMap, indexBound));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Node* AbstractContainerNode::findNode(XMLString::const_iterator& it, const XMLString::const_iterator& end, const Node* pNode, const NSMap* pNSMap)
|
const Node* AbstractContainerNode::findNode(XMLString::const_iterator& it, const XMLString::const_iterator& end, const Node* pNode, const NSMap* pNSMap, bool& indexBound)
|
||||||
{
|
{
|
||||||
|
indexBound = false;
|
||||||
if (pNode && it != end)
|
if (pNode && it != end)
|
||||||
{
|
{
|
||||||
if (*it == '[')
|
if (*it == '[')
|
||||||
@ -406,7 +409,8 @@ const Node* AbstractContainerNode::findNode(XMLString::const_iterator& it, const
|
|||||||
while (it != end && *it != ']') value += *it++;
|
while (it != end && *it != ']') value += *it++;
|
||||||
}
|
}
|
||||||
if (it != end) ++it;
|
if (it != end) ++it;
|
||||||
return findNode(it, end, findElement(attr, value, pNode, pNSMap), pNSMap);
|
bool ib;
|
||||||
|
return findNode(it, end, findElement(attr, value, pNode, pNSMap), pNSMap, ib);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -416,17 +420,19 @@ const Node* AbstractContainerNode::findNode(XMLString::const_iterator& it, const
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
XMLString index;
|
XMLString xmlIndex;
|
||||||
while (it != end && *it != ']') index += *it++;
|
while (it != end && *it != ']') xmlIndex += *it++;
|
||||||
if (it != end) ++it;
|
if (it != end) ++it;
|
||||||
#ifdef XML_UNICODE_WCHAR_T
|
#ifdef XML_UNICODE_WCHAR_T
|
||||||
std::string idx;
|
std::string index;
|
||||||
Poco::UnicodeConverter::convert(index, idx);
|
Poco::UnicodeConverter::convert(xmlIndex, index);
|
||||||
int i = Poco::NumberParser::parse(idx);
|
|
||||||
#else
|
|
||||||
int i = Poco::NumberParser::parse(index);
|
int i = Poco::NumberParser::parse(index);
|
||||||
|
#else
|
||||||
|
int i = Poco::NumberParser::parse(xmlIndex);
|
||||||
#endif
|
#endif
|
||||||
return findNode(it, end, findElement(i, pNode, pNSMap), pNSMap);
|
indexBound = true;
|
||||||
|
bool ib;
|
||||||
|
return findNode(it, end, findElement(i, pNode, pNSMap), pNSMap, ib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -440,8 +446,9 @@ const Node* AbstractContainerNode::findNode(XMLString::const_iterator& it, const
|
|||||||
const Node* pElem = findElement(key, pNode->firstChild(), pNSMap);
|
const Node* pElem = findElement(key, pNode->firstChild(), pNSMap);
|
||||||
while (!pFound && pElem)
|
while (!pFound && pElem)
|
||||||
{
|
{
|
||||||
pFound = findNode(it, end, pElem, pNSMap);
|
bool ib;
|
||||||
if (!pFound) pElem = findElement(key, pElem->nextSibling(), pNSMap);
|
pFound = findNode(it, end, pElem, pNSMap, ib);
|
||||||
|
if (!pFound) pElem = ib ? nullptr : findElement(key, pElem->nextSibling(), pNSMap);
|
||||||
it = itStart;
|
it = itStart;
|
||||||
}
|
}
|
||||||
return pFound;
|
return pFound;
|
||||||
|
@ -616,7 +616,7 @@ void ElementTest::testNodeByPath()
|
|||||||
<elemA/>
|
<elemA/>
|
||||||
<elemA/>
|
<elemA/>
|
||||||
</elem1>
|
</elem1>
|
||||||
<elem2>
|
<elem2 index="0">
|
||||||
<elemB attr1="value1"/>
|
<elemB attr1="value1"/>
|
||||||
<elemB attr1="value2"/>
|
<elemB attr1="value2"/>
|
||||||
<elemB attr1="value3"/>
|
<elemB attr1="value3"/>
|
||||||
@ -626,8 +626,9 @@ void ElementTest::testNodeByPath()
|
|||||||
</elemC>
|
</elemC>
|
||||||
<elemC attr1="value2"/>
|
<elemC attr1="value2"/>
|
||||||
</elem2>
|
</elem2>
|
||||||
<elem2>
|
<elem2 index="1">
|
||||||
<elemB attr1="value4"/>
|
<elemB attr1="value4"/>
|
||||||
|
<elemD attr1="value1"/>
|
||||||
</elem2>
|
</elem2>
|
||||||
</root>
|
</root>
|
||||||
*/
|
*/
|
||||||
@ -646,6 +647,10 @@ void ElementTest::testNodeByPath()
|
|||||||
AutoPtr<Element> pElem25 = pDoc->createElement("elemC");
|
AutoPtr<Element> pElem25 = pDoc->createElement("elemC");
|
||||||
AutoPtr<Element> pElem3 = pDoc->createElement("elem2");
|
AutoPtr<Element> pElem3 = pDoc->createElement("elem2");
|
||||||
AutoPtr<Element> pElem31 = pDoc->createElement("elemB");
|
AutoPtr<Element> pElem31 = pDoc->createElement("elemB");
|
||||||
|
AutoPtr<Element> pElem32 = pDoc->createElement("elemD");
|
||||||
|
|
||||||
|
pElem2->setAttribute("index", "0");
|
||||||
|
pElem3->setAttribute("index", "1");
|
||||||
|
|
||||||
pElem21->setAttribute("attr1", "value1");
|
pElem21->setAttribute("attr1", "value1");
|
||||||
pElem22->setAttribute("attr1", "value2");
|
pElem22->setAttribute("attr1", "value2");
|
||||||
@ -655,6 +660,7 @@ void ElementTest::testNodeByPath()
|
|||||||
pElem25->setAttribute("attr1", "value2");
|
pElem25->setAttribute("attr1", "value2");
|
||||||
|
|
||||||
pElem31->setAttribute("attr1", "value4");
|
pElem31->setAttribute("attr1", "value4");
|
||||||
|
pElem32->setAttribute("attr1", "value1");
|
||||||
|
|
||||||
AutoPtr<Element> pElem241 = pDoc->createElement("elemC1");
|
AutoPtr<Element> pElem241 = pDoc->createElement("elemC1");
|
||||||
AutoPtr<Element> pElem242 = pDoc->createElement("elemC2");
|
AutoPtr<Element> pElem242 = pDoc->createElement("elemC2");
|
||||||
@ -671,6 +677,7 @@ void ElementTest::testNodeByPath()
|
|||||||
pElem2->appendChild(pElem25);
|
pElem2->appendChild(pElem25);
|
||||||
|
|
||||||
pElem3->appendChild(pElem31);
|
pElem3->appendChild(pElem31);
|
||||||
|
pElem3->appendChild(pElem32);
|
||||||
|
|
||||||
pRoot->appendChild(pElem1);
|
pRoot->appendChild(pElem1);
|
||||||
pRoot->appendChild(pElem2);
|
pRoot->appendChild(pElem2);
|
||||||
@ -750,11 +757,32 @@ void ElementTest::testNodeByPath()
|
|||||||
pNode = pDoc->getNodeByPath("//[@attr1='value1']");
|
pNode = pDoc->getNodeByPath("//[@attr1='value1']");
|
||||||
assertTrue (pNode == pElem21);
|
assertTrue (pNode == pElem21);
|
||||||
|
|
||||||
|
pNode = pDoc->getNodeByPath("//[@attr1='value4']");
|
||||||
|
assertTrue (pNode == pElem31);
|
||||||
|
|
||||||
pNode = pDoc->getNodeByPath("//[@attr1='value2']");
|
pNode = pDoc->getNodeByPath("//[@attr1='value2']");
|
||||||
assertTrue (pNode == pElem22);
|
assertTrue (pNode == pElem22);
|
||||||
|
|
||||||
pNode = pRoot->getNodeByPath("/elem2/*[@attr1='value2']");
|
pNode = pRoot->getNodeByPath("/elem2/*[@attr1='value2']");
|
||||||
assertTrue (pNode == pElem22);
|
assertTrue (pNode == pElem22);
|
||||||
|
|
||||||
|
pNode = pDoc->getNodeByPath("/root/elem2[0]/elemC");
|
||||||
|
assertTrue (pNode == pElem24);
|
||||||
|
|
||||||
|
pNode = pDoc->getNodeByPath("/root/elem2[1]/elemC");
|
||||||
|
assertTrue (pNode == 0);
|
||||||
|
|
||||||
|
pNode = pDoc->getNodeByPath("/root/elem2[0]/elemD");
|
||||||
|
assertTrue (pNode == 0);
|
||||||
|
|
||||||
|
pNode = pDoc->getNodeByPath("/root/elem2[1]/elemD");
|
||||||
|
assertTrue (pNode == pElem32);
|
||||||
|
|
||||||
|
pNode = pDoc->getNodeByPath("/root/elem2[@index=0]/elemD");
|
||||||
|
assertTrue (pNode == 0);
|
||||||
|
|
||||||
|
pNode = pDoc->getNodeByPath("/root/elem2[@index=1]/elemD");
|
||||||
|
assertTrue (pNode == pElem32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user