From 0ab3681656897b9c192558d5a929a83384156c27 Mon Sep 17 00:00:00 2001 From: Lodovico Giaretta Date: Mon, 7 Nov 2016 17:27:44 +0100 Subject: [PATCH] Fix wrong recursion in getElementsByTagName implementation; close #35 --- source/std/experimental/xml/domimpl.d | 57 +++++++++++-------------- source/std/experimental/xml/domparser.d | 16 ++++--- 2 files changed, 37 insertions(+), 36 deletions(-) diff --git a/source/std/experimental/xml/domimpl.d b/source/std/experimental/xml/domimpl.d index c283aac..b6ff961 100644 --- a/source/std/experimental/xml/domimpl.d +++ b/source/std/experimental/xml/domimpl.d @@ -1091,28 +1091,34 @@ class DOMImplementation(DOMString, Alloc = shared(GCAllocator), ErrorHandler = b else private DOMString tagname; - private Element findNext(Node node) + private bool check(Node node) { - foreach (item; node.childNodes) + static if (ns) { - static if (ns) + if (node.nodeType == dom.NodeType.element) { - if (item.nodeType == dom.NodeType.element) - { - auto elem = cast(Element)item; - if (elem.namespaceURI == namespaceURI && elem.localName == localName) - return elem; - } + auto elem = cast(Element)node; + return elem.namespaceURI == namespaceURI && elem.localName == localName; } else - if (item.nodeType == dom.NodeType.element && item.nodeName == tagname) - return cast(Element)item; + return false; + } + else + return node.nodeType == dom.NodeType.element && node.nodeName == tagname; + } - auto res = findNext(item); - if (res !is null) - return res; + private Element findNext(Node node) + { + if (node.firstChild) + { + auto item = node.firstChild; + if (check(item)) + return cast(Element)item; + else + return findNext(item); } - return findNextBack(node); + else + return findNextBack(node); } private Element findNextBack(Node node) { @@ -1120,25 +1126,13 @@ class DOMImplementation(DOMString, Alloc = shared(GCAllocator), ErrorHandler = b { auto item = node.nextSibling; - static if (ns) - { - if (item.nodeType == dom.NodeType.element) - { - auto elem = cast(Element)item; - if (elem.namespaceURI == namespaceURI && elem.localName == localName) - return elem; - } - } + if (check(item)) + return cast(Element)item; else - if (item.nodeType == dom.NodeType.element && item.nodeName == tagname) - return cast(Element)item; - - return findNext(item); + return findNext(item); } - else if (node.parentNode && node.parentNode !is root) - { + else if (node.parentNode && node.parentNode !is node.ownerDocument) return findNextBack(node.parentNode); - } else return null; } @@ -1152,6 +1146,7 @@ class DOMImplementation(DOMString, Alloc = shared(GCAllocator), ErrorHandler = b auto node = findNext(root); while (node !is null) { + //writeln("Found node ", node.nodeName); res++; node = findNext(node); } diff --git a/source/std/experimental/xml/domparser.d b/source/std/experimental/xml/domparser.d index 06712f0..69fe53b 100644 --- a/source/std/experimental/xml/domparser.d +++ b/source/std/experimental/xml/domparser.d @@ -60,12 +60,8 @@ struct DOMBuilder(T, DOMImplementation = dom.DOMImplementation!(T.StringType)) domImpl = impl; } - /++ - + Initializes this builder and the underlying components. - +/ - void setSource(T.InputType input) + private void initialize() { - cursor.setSource(input); document = domImpl.createDocument(null, null, null); if (cursor.kind == XMLKind.document) @@ -85,6 +81,15 @@ struct DOMBuilder(T, DOMImplementation = dom.DOMImplementation!(T.StringType)) currentNode = document; } + /++ + + Initializes this builder and the underlying components. + +/ + void setSource(T.InputType input) + { + cursor.setSource(input); + initialize(); + } + /++ + Same as `cursor.enter`. When entering a node, that node is automatically + built into the DOM, so that its children can then be safely built if needed. @@ -212,6 +217,7 @@ auto domBuilder(CursorType, DOMImplementation)(auto ref CursorType cursor, DOMIm auto res = DOMBuilder!(CursorType, DOMImplementation)(); res.cursor = cursor; res.domImpl = impl; + res.initialize; return res; }