haysclark / as3-xpath

1 stars 0 forks source link

XPath result is a copy of the original XML object #12

Closed haysclark closed 9 years ago

haysclark commented 9 years ago

From peterj...@gmail.com on January 08, 2008 16:16:55

The result of XPath.exec() is based on a copy of the XML object. That means, you cannot select some nodes and modify them, because the changes won't affect the original.

Mailing list thread:

On Jan 8, 2008 7:05 PM, Peter Hall (peterjoel) wrote: Hi, Currently, the original XML object is copied before anything else happens. It's probably possible to do this a different way, but I'll try to explain why it works like that now, for the record.

Let's take a simple example XML object: var xmlObj:XML = . The root element is the node and, in e4X, this is the whole XML object, equal to xmlObject, and nothing can exist outside of it. But in XPath the document root is a level above that, and can contain processing instructions, comments, whitespace, as well as the root element. In XPath, you must select the root element as a child of the root document: "/a/b", while in e4x you already have the root element, so you just use xmlObj.b.

To resolve this difference, if you execute a query on a root XML node, I wrap the node inside another document root, so that it can be addressed as a child. This actually means changing the XML (the parent() property will now return the wrapper node instead of null), so I made a copy to make sure that XPath didn't cause unexpected problems elsewhere in your application.

In a previous version of the library, I was not using a copy, but removing the wrapper before returning the result. The problem here is, if you add custom functions or variables that are getters, it's possible to "call out" of the query in the middle of it being executed. It's probably a small use-case, but I can imagine it causing hard to find bugs, in particular if new XPath queries are made on the same object and causes the XML to get wrapped twice.

A third option would be to make it the responsibility of the library user to wrap the XML. But that feels like it is introducing too many pitfalls for users to get wrong, so I threw that option out a long time ago.

I will try to take a look at ways of getting around this, without returning a copy, but it won't be until the weekend at least. If you want to have a poke around in the code yourself, it's all in memorphic.xpath.model.QueryRoot. If you go back to revision 16 , you will see how I was originally doing it. A couple of the unit tests will fail if you just revert that file but it might be good enough for your needs.

If you are going to look at fixing it yourself, I remember one big problem that held me up was that Dictionary doesn't allow XML objects to be used as keys - I think I was trying that approach to track if the root node was already wrapped. Another problem I came across is that adding a unique namespace to the wrapper node pollutes (incorrectly) the output of toXMLString() for the rest of the document, so you can't use that as a check. If you do have a go at it I'll help you where I can.

Cheers,

Peter

On Jan 8, 2008 5:25 PM, rforte wrote:

I'm trying to do an XPathQuery on a piece of XML and then update the value. I followed the instructions here: http://groups.google.com/group/xpath-as3/browse_thread/thread/7929b1384b6bcc5b?hl=en-GB > but it's not working quite right for me. However, this doesn't update the source XML. It only updates the XML returned from the XPath query. This would suggest that the XPath query returns a copy of the result rather than a reference to the source XML. Here's my code:

private function ChangeXML() : void { var document:XML =

Montrose
                                 <timeout time="87">
                                     <value>123</value>
                                 </timeout>
                                 <voltage mtime="32"

id="input">17.6 ;

var xpq:XPathQuery = new XPathQuery("/document/location[1]")
var node:XML = xpq.exec(document)[0];

node.parent().children()[node.childIndex()] = "abc";

trace( 'ChangedXML ' + document );
trace( 'node ' + node.toXMLString() );

}

Original issue: http://code.google.com/p/xpath-as3/issues/detail?id=12

haysclark commented 9 years ago

From peterj...@gmail.com on January 11, 2008 19:47:04

Status: Fixed

haysclark commented 9 years ago

From peterj...@gmail.com on April 14, 2009 00:10:30

Verifying old bug fixes

Status: Verified