Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

XML firstChild issue

Moderators: kris

Posted: 02/18/09 04:03:15

Hello everyone.

Today is actually my first day with Tango, after deciding that Phobos just wasn't cutting it. I am in the middle of remaking one of my projects and implementing some xml loading into it, but i've run into what seems to me as a bug. I'm not sure if I have the latest version of tango though (I used the package for ubuntu 8.10, installed today), as my tango.text.xml.Document file doesn't match that in the online documentation (I have firstChild instead of just child...)

But, here goes: When I have a NodeImpl?, say tNode. When I do tNode.firstChild(), I get a mystery node that is not defined in my xml file (i even removed all white space). Then if I do tNode = tNode.firstChild().nextSibling() I get the proper first child of my element.

Is this a known issue or do I just have an out dated version of tango installed? (If the later, how would I go about updating my current install?)

~Wolftousen

Author Message

Posted: 02/18/09 05:46:38

How do you obtain the initial node? Better yet, do you have a tiny example that shows this, please?

Thanks much :)

Posted: 02/18/09 06:54:21

Just to chime in, I think the Ubuntu packages where generated prior to some recent changes in the XML api, although it should be naming mostly. Maybe this tutorial helps a bit? I think it was updated with the latest changes.

Posted: 02/18/09 07:50:01

The 0.99.7 docs are here: http://dil.googlecode.com/svn/doc/Tango_0.99.7/tango.text.xml.Document.html

If you're at the document root, you need to use doc.root.lastChild to access the root element itself. Don't know if that helps.

Posted: 02/18/09 17:28:59

Ah, right. Perhaps that's related to the stuff that's been changed. The true root of an XML document is generally the document itself, rather than the first element. That's because things like PI tags are siblings to the first element. This aspect was addressed via some name changes in a more recent revision.

Posted: 02/18/09 18:55:50

Here is the example in my code that is causing the issue. if the .deb package hasn't been updated to 0.99.7 then I don't have the newest version and this error might be fixed already, but someone may want to try it just to make sure since the updates were mostly syntax...

//open up the file

auto file = new File(filename);

//make sure the file opened properly

if(file is null)

return false;

//initialize and fill a buffer

char[] xml = cast(char[])file.read(); //define a document and parse the file

auto doc = new Document!(char);

doc.parse(xml); auto root = doc.root.firstChild; foreach(texture; root.query.child("texture")) {

if(!texture.hasChildren())

continue;

//this is were the problem is, if i were to leave off .nextSibling, it would give me a mystery element...

auto element = texture.firstChild().nextSibling();

}

Posted: 02/18/09 19:01:37 -- Modified: 02/18/09 19:02:13 by
torhu

Replace auto root = doc.root.firstChild;

with: auto root = doc.root.lastChild;

Posted: 02/18/09 21:31:04

Same issue occurs with that change (either using doc.root.firstChild or doc.root.lastChild)

My file is as such:

<graphics>

<texture>

<src>font.bmp</src>

<id>font</id>

</texture>

<texture>

<src>test.bmp</src>

<id>test</id>

</texture>

</graphics>

Here is a loop I put in to further test:

auto root = doc.root.lastChild;

foreach(child; root.query.child("texture"))
		{
			if(!child.hasChildren())
				continue;
			auto element = child.firstChild();
			Stdout.format("Value: {}\n", element.value());
			if(element is null || element.name() != "src")
			    Stdout("Found no src...\n");
		}

When run, I get ouput:

Value:

Found no source...

Value:

Found no source...

When I use child.firstChild().nextSibling() I get the following (which is the correct output):

Value: font.bmp

Value: test.bmp

Doing child.lastChild also doesn't work...

Posted: 02/19/09 00:15:49

think I see part of what's going on here ... data content is explicitly a child of a hosting element. For example:

<src>font.bmp</src> 

This has an element node <src> and a child text node "font.bmp". If the element had attributes, those would also be represented as additional (subordinate) nodes. I suspect the ghost node you're seeing is perhaps the element itself? A variety of functions hide this distinction (the value() method, for example) although explicit tree-traversal does not.

BTW, this is perhaps the kind of thing that XPath notation should be good at hiding? I think the following may select the nodes you want (using code in trunk):

foreach (node; doc.root.descendant("texture").data)
         Stdout(node.value).newline;

(untested)

Posted: 02/19/09 01:39:06

That gives the same output as with root.query.child()...

auto root = doc.root.firstChild;
		
foreach(texture; root.query.descendant("texture"))
{
  if(!texture.hasChildren())
     Stdout("Invalid Texture\n");
  auto element = texture.firstChild();
  Stdout("Found a texture\n");
  Stdout.format("Value: {}\n", element.value());
}

It is hard to format the output it gives in this forum for some reason... but it does:

Found a texture
Value:

Found a texture
Value:

Notice that it isn't printing nothing as the value, it is printing an extra newline at the very least (can't tell if there are spaces in my console...)

The query is finding the right number of textures, but each element the query gives me no matter how many child elements it has, has a "blank" element as it's first child element for some reason. Beyond that "blank" first texture everything is working fine as I've worked around it since it is a consistent case.

I don't really want to use descendant because I don't want texture objects if they are embedded in other objects, they need to be direct children of the root to be valid for me.

Posted: 02/19/09 06:56:13

seems to operate as expected with trunk ... not sure what else to suggest