Knoten ohne Typ?
Deus Figendi
- javascript
Guten Morgen,
ich wollte mich ein bisschen mit der parseFromString-Methode des DOMParser-Objekts beschäftigen, da ich manchmal AJAX-Antworten bekomme, die zwar XML sind aber nicht als XML ausgeliefert werden, was dazu führt, dass das responseXML nicht zur Verfügung steht. Außerdem fand ich es einfach interessant auch in UI-Elementen XML entgegen nehmen zu können.
Daher habe ich das folgende Script geschrieben (nicht wundern, ist an ein paar Stellen "dirty" aber ist ja auch nur ein Test):
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
[code lang=css] #debuglist {
width:50%;
font-size:x-small;
}
#debuglist div {
float:left;
}
</style>
<script type="text/javascript">~~~javascript
function debug_print(text) {
var debug_li = document.createElement("li");
debug_li.appendChild(document.createTextNode(text));
document.getElementById("debuglist").appendChild(debug_li);
}
function parsearea () {
var XML_string = '';
debug_print (XML_string);
var XML_string = document.getElementById("fooooo").value;
debug_print (XML_string);
var XML_object = (new DOMParser()).parseFromString(XML_string, "text/xml");
debug_print (XML_object.childNodes[0].childNodes.length);
report_XML_Object(XML_object.childNodes[0],' ');
}
function report_XML_Object (xmlnode,path) {
if (xmlnode.nodeType == 1) {
var path = path+'<'+xmlnode.nodeName+'>';
} else if (xmlnode.nodeType == 2) {
var path = path+'.'+xmlnode.nodeName;
} else if (xmlnode.nodeType == 3) {
var path = path+'"'+xmlnode.data+'"';
} else if (xmlnode.nodeType == 4) {
var path = path+'('+xmlnode.data+')';
} else {
var path = path+'['+xmlnode.nodeType+']';
}
debug_print (path);
for (var i in xmlnode.childNodes) {
report_XML_Object(xmlnode.childNodes[i],path);
}
}
</script>
</head>
<body>
<ul id="debuglist">
<div>
<form>
<textarea id="fooooo" cols="30" rows="20"><?xml version="1.0"?>
<root\_element>
<sub\_element num="1" />
<sub\_element num="2" />
<sub\_element num="3">
Textcontent of subelement3
</sub\_element>
</root\_element></textarea>
<input type="button" value="parse it" onclick="parsearea();"/>
</form>
</div></ul>
</body>
</html>
[/code]
Das seltsame Resultat, welches ich erhalte ist
# 7
# <root\_element>
# <root\_element>" "
# <root\_element>" "[undefined]
# <root\_element>" "[undefined]
# <root\_element><sub\_element>
# <root\_element><sub\_element>[undefined]
# <root\_element><sub\_element>[undefined]
# <root\_element>" "
# <root\_element>" "[undefined]
# <root\_element>" "[undefined]
# <root\_element><sub\_element>
# <root\_element><sub\_element>[undefined]
# <root\_element><sub\_element>[undefined]
# <root\_element>" "
# <root\_element>" "[undefined]
# <root\_element>" "[undefined]
# <root\_element><sub\_element>
# <root\_element><sub\_element>" Textcontent of subelement3 "
# <root\_element><sub\_element>" Textcontent of subelement3 "[undefined]
# <root\_element><sub\_element>" Textcontent of subelement3 "[undefined]
# <root\_element><sub\_element>[undefined]
# <root\_element><sub\_element>[undefined]
# <root\_element>" "
# <root\_element>" "[undefined]
# <root\_element>" "[undefined]
# <root\_element>[undefined]
# <root\_element>[undefined]
Mit den ersten drei Ausgaben komme ich noch gut Zurecht, es sind sieben Kindelemente... hab' ich gezählt, stimmt.
Das erste ist das root\_element-Element stimmt auch. Das erste Kindelement des root\_element ist ein Textknoten, der einen Zeilenumbruch sowie ein Leerzeichen darstellt, aber ab dann verstehe ich's nicht mehr.
Warum hat der Textknoten zwei Kindknoten vom \_Typ\_ "undefined"? Kann denn überhaupt ein Knoten existieren, der keinen Typ hat?
Wie man sieht zieht sich das durch alle Elemente durch, nach allen Kindknoten kommen noch zwei undefinierte (sieht man ganz gut daran, dass es beim root\_element am Ende der Liste steht).
Weiß jemand woher die kommen und was sie sind?
--
sh:( fo:| ch:? rl:( br:& n4:& ie:{ mo:} va:) de:µ\_de:] zu:) fl:( ss:| ls:[ js:(
Im Gespräch mit jemandem ist mir gerade aufgefallen, dass man das Beispiel ja auch massiv vereinfach kann ^^ also oben genannter Code parst:
<?xml version="1.0"?>
<root_element/>
und spuckt aus:
# <root_element>
Okay, ich habe gerade noch ein bisschen herumgespielt und scheinbar haben XML-Knoten _Kinder_ (childNodes[]!!!), die Zahlen oder Funktionen sind.
Ich habe den Code nämlich folgendermaßen geändert:
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>[code lang=css]
#debuglist {
font-size:x-small;
}
#debuglist div {
float:left;
}
</style>
<script type="text/javascript">~~~javascript
function debug_print(text) {
var debug_li = document.createElement("li");
debug_li.appendChild(document.createTextNode(text));
document.getElementById("debuglist").appendChild(debug_li);
}
function parsearea () {
var XML_string = '';
debug_print (XML_string);
var XML_string = document.getElementById("fooooo").value;
debug_print (XML_string);
var XML_object = (new DOMParser()).parseFromString(XML_string, "text/xml");
debug_print (XML_object.childNodes.length);
debug_print (XML_object.childNodes[0].childNodes.length);
report_XML_Object(XML_object.childNodes[0],' ');
}
function report_XML_Object (xmlnode,path) {
if (xmlnode.nodeType == 1) {
var path = path+'<'+xmlnode.nodeName+'>';
} else if (xmlnode.nodeType == 2) {
var path = path+'.'+xmlnode.nodeName;
} else if (xmlnode.nodeType == 3) {
var path = path+'"'+xmlnode.data+'"';
} else if (xmlnode.nodeType == 4) {
var path = path+'('+xmlnode.data+')';
} else {
var path = path+'['+xmlnode.nodeType+' _ '+typeof(xmlnode)+' _ '+xmlnode+']';
}
debug_print (path);
for (var i in xmlnode.childNodes) {
report_XML_Object(xmlnode.childNodes[i],path);
}
}
</script>
</head>
<body>
<ul id="debuglist">
<div>
<form>
<textarea id="fooooo" cols="30" rows="20"><?xml version="1.0"?>
<root\_element/></textarea>
<input type="button" value="parse it" onclick="parsearea();"/>
</form>
</div></ul>
</body>
</html>
[/code]
Und da fällt folgendes raus in Gecko:
# <?xml version="1.0"?> <root\_element/>
# 1
# 0
# <root\_element>
# <root\_element>[\_undefined \_ number \_ 0\_]
# <root\_element>[\_undefined \_ function \_ function item() { [native code] }\_]
und in Presto/Opera (veralterte Version):
# <?xml version="1.0"?> <root\_element/>
# 1
# 0
# <root\_element>
# <root\_element>[\_undefined \_ number \_ 0\_]
# <root\_element>[\_undefined \_ function \_ function item() { [native code] }\_]
# <root\_element>[\_undefined \_ function \_ function namedItem() { [native code] }\_]
# <root\_element>[\_undefined \_ function \_ function tags() { [native code] }\_]
Damit ist klar, dass ich sie zumindest bei der Verarbeitung identifizieren kann (weil typeof() bei XML-Knoten eigentlich immer object zurück geben sollte).
Aber seltsam finde ich das Verhalten dennoch. Weiß jemand warum das DOMParser-Objekt diese Dinger als Kinder angibt? Als Methoden o.ä. fände ich es ja normal also wenn die for-in-Schleife durch xmlnode liefe, aber sie läuft ja durch xmlnode.childNodes und da irritiert mich das gerade ein wenig.
--
sh:( fo:| ch:? rl:( br:& n4:& ie:{ mo:} va:) de:µ\_de:] zu:) fl:( ss:| ls:[ js:(
Hallo,
verrenne Dich nicht. Dein Problem liegt hier:
function report_XML_Object (xmlnode,path) {
...
for (var i in xmlnode.childNodes) {
report_XML_Object(xmlnode.childNodes[i],path);
}
for in durchläuft das Objekt mit allen seinen _Eigenschaften_ und _Methoden_. Dazu gehören hier _auch_ die childNodes, aber eben _auch_. Es gehört z.B. auch die Methode item() dazu.
for (var i= 0; i < xmlnode.childNodes.lenght; i++) {
report_XML_Object(xmlnode.childNodes[i],path);
}
viele Grüße
Axel
Hallo,
for (var i= 0; i < xmlnode.childNodes.lenght; i++) {
report_XML_Object(xmlnode.childNodes[i],path);
}
length natürlich richtig schreiben ;-)
viele Grüße
Axel
for in durchläuft das Objekt mit allen seinen _Eigenschaften_ und _Methoden_. Dazu gehören hier _auch_ die childNodes, aber eben _auch_. Es gehört z.B. auch die Methode item() dazu.
Ja das habe ich ja nun auch mitbekommen, allerdings kannte ich die Methoden item() oder namedItem() nicht und ich weiß auch nicht was die machen. Kennst du eine Refferenz dazu? Zum node-Objekt scheinen sie ja nicht zu gehören (zumindest nicht lt. self 8.1.2)
lenght
length natürlich richtig schreiben ;-)
Den Tippfehler mache ich auch ständig ^^ liegt wohl an der Nähe der drei Zeichen t,g und h in üblichen Layouts.
Hallo,
for in durchläuft das Objekt mit allen seinen _Eigenschaften_ und _Methoden_. Dazu gehören hier _auch_ die childNodes, aber eben _auch_. Es gehört z.B. auch die Methode item() dazu.
Ja das habe ich ja nun auch mitbekommen, allerdings kannte ich die Methoden item() oder namedItem() nicht und ich weiß auch nicht was die machen. Kennst du eine Refferenz dazu? Zum node-Objekt scheinen sie ja nicht zu gehören (zumindest nicht lt. self 8.1.2)
Du durchläufst mit [Node].childNodes eine NodeList.
viele Grüße
Axel
Dank dir.
allerdings kannte ich die Methoden item() oder namedItem() nicht
item(i) ist die Methode, die intern aufgerufen wird, wenn man in JavaScript nodelist[i] schreibt. namedItem("foo") wird aufgerufen, wenn man nodelist.foo bzw. nodelist["foo"] schreibt. Siehe auch DOM 2 HTML ECMAScript Binding.
Mathias