diff --git a/src/pugixml.cpp b/src/pugixml.cpp
index 8b2f35cb7560b7954de8e0472875bc1bced168dc..c65fc906a150fc396dfaaeddb73498c910385515 100644
--- a/src/pugixml.cpp
+++ b/src/pugixml.cpp
@@ -3336,14 +3336,9 @@ namespace pugi
 		return (_attr && _attr->value) ? _attr->value : PUGIXML_TEXT("");
 	}
 
-	const void* xml_attribute::document_order() const
+	xml_attribute_struct* xml_attribute::internal_object()
 	{
-		if (!_attr) return 0;
-
-		if ((_attr->header & xml_memory_page_name_allocated_mask) == 0) return _attr->name;
-		if ((_attr->header & xml_memory_page_value_allocated_mask) == 0) return _attr->value;
-
-		return 0;
+        return _attr;
 	}
 
 	xml_attribute& xml_attribute::operator=(const char_t* rhs)
@@ -4054,14 +4049,9 @@ namespace pugi
 		return walker.end(arg_end);
 	}
 
-	const void* xml_node::document_order() const
+	xml_node_struct* xml_node::internal_object()
 	{
-		if (!_root) return 0;
-
-		if (_root->name && (_root->header & xml_memory_page_name_allocated_mask) == 0) return _root->name;
-		if (_root->value && (_root->header & xml_memory_page_value_allocated_mask) == 0) return _root->value;
-
-		return 0;
+        return _root;
 	}
 
 	void xml_node::print(xml_writer& writer, const char_t* indent, unsigned int flags, xml_encoding encoding, unsigned int depth) const
@@ -5351,19 +5341,43 @@ namespace
 
     	return parent && node == parent;
     }
+
+    const void* document_order(const xpath_node& xnode)
+    {
+        xml_node_struct* node = xnode.node().internal_object();
+
+        if (node)
+        {
+            if (node->name && (node->header & xml_memory_page_name_allocated_mask) == 0) return node->name;
+            if (node->value && (node->header & xml_memory_page_value_allocated_mask) == 0) return node->value;
+            return 0;
+        }
+
+        xml_attribute_struct* attr = xnode.attribute().internal_object();
+
+        if (attr)
+        {
+            if ((attr->header & xml_memory_page_name_allocated_mask) == 0) return attr->name;
+            if ((attr->header & xml_memory_page_value_allocated_mask) == 0) return attr->value;
+            return 0;
+        }
+
+		return 0;
+    }
     
 	struct document_order_comparator
 	{
 		bool operator()(const xpath_node& lhs, const xpath_node& rhs) const
 		{
-			xml_node ln = lhs.node(), rn = rhs.node();
-
 			// optimized document order based check
-			const void* lo = lhs.attribute() ? lhs.attribute().document_order() : ln.document_order();
-			const void* ro = rhs.attribute() ? rhs.attribute().document_order() : rn.document_order();
+			const void* lo = document_order(lhs);
+			const void* ro = document_order(rhs);
 
 			if (lo && ro) return lo < ro;
 
+            // slow comparison
+			xml_node ln = lhs.node(), rn = rhs.node();
+
 			// compare attributes
 			if (lhs.attribute() && rhs.attribute())
 			{
diff --git a/src/pugixml.hpp b/src/pugixml.hpp
index 80fe6d80f89fc1021111fdc7d2195e81fc88f194..2624362e88824304a42e1b222688826fc2335b3f 100644
--- a/src/pugixml.hpp
+++ b/src/pugixml.hpp
@@ -254,12 +254,13 @@ namespace pugi
 	
     	typedef xml_attribute_struct* xml_attribute::*unspecified_bool_type;
 
-		explicit xml_attribute(xml_attribute_struct* attr);
-
 	public:
         // Default constructor. Constructs an empty attribute.
 		xml_attribute();
 		
+        // Constructs attribute from internal pointer
+		explicit xml_attribute(xml_attribute_struct* attr);
+
     	// Safe bool conversion operator
     	operator unspecified_bool_type() const;
 
@@ -311,8 +312,8 @@ namespace pugi
     	xml_attribute next_attribute() const;
     	xml_attribute previous_attribute() const;
 
-		// This function is for internal use
-		const void* document_order() const;
+		// Get internal pointer
+		xml_attribute_struct* internal_object();
 	};
 
 #ifdef __BORLANDC__
@@ -332,12 +333,13 @@ namespace pugi
 
     	typedef xml_node_struct* xml_node::*unspecified_bool_type;
 
-		explicit xml_node(xml_node_struct* p);
-
 	public:
 		// Default constructor. Constructs an empty node.
 		xml_node();
 
+        // Constructs node from internal pointer
+		explicit xml_node(xml_node_struct* p);
+
     	// Safe bool conversion operator
 		operator unspecified_bool_type() const;
 
@@ -521,8 +523,8 @@ namespace pugi
 		// Get node offset in parsed file/string (in char_t units) for debugging purposes
 		ptrdiff_t offset_debug() const;
 
-		// This function is for internal use
-		const void* document_order() const;
+		// Get internal pointer
+		xml_node_struct* internal_object();
 	};
 
 #ifdef __BORLANDC__