XPath: Fixed document order comparator (wrong attributes comparison in case of added ones, buggy LCA determination)
git-svn-id: http://pugixml.googlecode.com/svn/trunk@109 99668b35-9821-0410-8761-19e4c4f06640
This commit is contained in:
parent
f57ab52894
commit
bf160df125
@ -125,6 +125,45 @@ namespace
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int node_height(xml_node n)
|
||||||
|
{
|
||||||
|
unsigned int result = 0;
|
||||||
|
|
||||||
|
while (n)
|
||||||
|
{
|
||||||
|
++result;
|
||||||
|
n = n.parent();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// precondition: node_height of ln is <= node_height of rn, ln != rn
|
||||||
|
bool node_is_before(xml_node ln, unsigned int lh, xml_node rn, unsigned int rh)
|
||||||
|
{
|
||||||
|
assert(lh <= rh);
|
||||||
|
|
||||||
|
while (lh < rh)
|
||||||
|
{
|
||||||
|
--rh;
|
||||||
|
rn = rn.parent();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ln == rn) return true;
|
||||||
|
|
||||||
|
while (ln.parent() != rn.parent())
|
||||||
|
{
|
||||||
|
ln = ln.parent();
|
||||||
|
rn = rn.parent();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (; ln; ln = ln.next_sibling())
|
||||||
|
if (ln == rn)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct document_order_comparator
|
struct document_order_comparator
|
||||||
{
|
{
|
||||||
bool operator()(const xpath_node& lhs, const xpath_node& rhs) const
|
bool operator()(const xpath_node& lhs, const xpath_node& rhs) const
|
||||||
@ -139,7 +178,14 @@ namespace
|
|||||||
|
|
||||||
if (lhs.attribute() && rhs.attribute())
|
if (lhs.attribute() && rhs.attribute())
|
||||||
{
|
{
|
||||||
if (lhs.parent() == rhs.parent()) return lhs.attribute() < rhs.attribute();
|
if (lhs.parent() == rhs.parent())
|
||||||
|
{
|
||||||
|
for (xml_attribute a = lhs.attribute(); a; a = a.next_attribute())
|
||||||
|
if (a == rhs.attribute())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ln = lhs.parent();
|
ln = lhs.parent();
|
||||||
rn = rhs.parent();
|
rn = rhs.parent();
|
||||||
@ -158,31 +204,11 @@ namespace
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ln == rn) return false;
|
if (ln == rn) return false;
|
||||||
|
|
||||||
xml_node lp = ln, rp = rn;
|
|
||||||
|
|
||||||
while (lp != rp)
|
|
||||||
{
|
|
||||||
ln = lp;
|
|
||||||
lp = lp.parent();
|
|
||||||
|
|
||||||
if (lp != rp)
|
|
||||||
{
|
|
||||||
rn = rp;
|
|
||||||
rp = rp.parent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!lp) // no common parent - ???
|
|
||||||
return false;
|
|
||||||
else // lp is parent, ln & rn are distinct siblings
|
|
||||||
{
|
|
||||||
for (; ln; ln = ln.next_sibling())
|
|
||||||
if (ln == rn)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
unsigned int lh = node_height(ln);
|
||||||
}
|
unsigned int rh = node_height(rn);
|
||||||
|
|
||||||
|
return (lh <= rh) ? node_is_before(ln, lh, rn, rh) : !node_is_before(rn, rh, ln, lh);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user