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:
arseny.kapoulkine 2009-01-19 11:18:34 +00:00
parent f57ab52894
commit bf160df125

View File

@ -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
{
bool operator()(const xpath_node& lhs, const xpath_node& rhs) const
@ -139,7 +178,14 @@ namespace
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();
rn = rhs.parent();
@ -158,31 +204,11 @@ namespace
}
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);
}
};