tags:

views:

292

answers:

2

I'm trying to use DOMParser, or XPath to get a XML fragment out of a document. A element with either DOMParser or document.evaluate returns an element with a null nodeValue, how do I get the xml fragment back as a string? Here's the example that I can't get to work in WebKit.

XML:

<fetch version="1.0" output-format="xml-platform" mapping="logical" distinct="false">
  <entity name="contact">
    <attribute name="address1_stateorprovince" />
    <attribute name="new_source" />
    <attribute name="ownerid" />
    <attribute name="new_organization" />
    <attribute name="new_lastcontacted" />
    <attribute name="emailaddress1" />
    <attribute name="address1_city" />
    <attribute name="telephone1" />
    <order attribute="fullname" descending="false" />
    <filter type="and">
      <condition attribute="new_conflicting" operator="eq" value="1" />
    </filter>
    <attribute name="fullname" />
    <attribute name="new_csuid" />
    <attribute name="new_contacttype" />
    <attribute name="contactid" />
  </entity>
</fetch>

Source:

var parser = new DOMParser();
var filterXmlDoc = parser.parseFromString(xml, "text/xml");
var test = filterXmlDoc.getElementsByTagName("filter")[0];
test.nodeValue; // null!
A: 

Try:

test.items(0).nodeValue;

getElementsByTagName() returns a NodeList so you must use items() method of that object.

Though ideally you would do:

if (test.length)
{
    console.log(test.items(0).nodeValue);
}
else
{
    console.log('Nothing Found');
}
Darrell Brogdon
I am already getting the first item returned from getElementsByTagName, nodeValue is null.
Boog
Right you are. Didn't notice that at first. Though I believe you still may want to use item() instead of the array element reference as the latter may have issues with other browsers.
Darrell Brogdon
+4  A: 

nodeValue is the "value" of the node, which for Element types is meaningless (and rightly null). It is not the xml string representation of the node.

For WebKit you can use XMLSerializer to get the string representation back out:

var xml = new XMLSerializer().serializeToString(test);
xml; // <filter type="and"><condition attribute="new_conflicting" operator="eq" value="1"/></filter>


Update re comment "Is there an easy way to only get the inner xml?":

You could construct a DocumentFragment from the child nodes, and serialize just the fragment:

var frag = filterXmlDoc.createDocumentFragment();
while(test.firstChild) {
  frag.appendChild(test.firstChild);
}
var xml = new XMLSerializer().serializeToString(frag);
xml; // <condition attribute="new_conflicting" operator="eq" value="1"/>

Note that this will empty out your test node after running.

Crescent Fresh
And here's WebKits unbelievably top-to-bottom documentation on `XMLSerializer`: http://developer.apple.com/mac/library/DOCUMENTATION/AppleApplications/Reference/WebKitDOMRef/XMLSerializer_idl/Classes/XMLSerializer/index.html
Crescent Fresh
Lol, a joke I take it? Is there an easy way to only get the inner xml?
Boog
@Boog: I think apple just might be serious. Re inner xml, see my updated answer. Hope it helps :)
Crescent Fresh
@Crescent Fresh: that's some great Jedi code! Thanks a million. My naive attempt was a for loop on childNodes but I like yours better, it's cleaner and simpler ;)
Boog
@Boog: the `for` loop isn't so bad, as it will still leave `test` node intact unlike my approach which rips its childNodes out. On the other hand, you'd be doing string collecting and [potentially] multiple calls to `serializeToString`, which is completely unnecessary. Meh.
Crescent Fresh