Skip to content

Commit

Permalink
Merge pull request #12 from burner/utf8
Browse files Browse the repository at this point in the history
UTF8 for the win + lot of housekeeping
  • Loading branch information
ZILtoid1991 authored Jan 8, 2024
2 parents 9654461 + 32520b3 commit 2c17e0e
Show file tree
Hide file tree
Showing 14 changed files with 2,534 additions and 2,437 deletions.
652 changes: 342 additions & 310 deletions source/newxml/cursor.d

Large diffs are not rendered by default.

371 changes: 215 additions & 156 deletions source/newxml/dom.d

Large diffs are not rendered by default.

2,097 changes: 1,256 additions & 841 deletions source/newxml/domimpl.d

Large diffs are not rendered by default.

148 changes: 70 additions & 78 deletions source/newxml/domparser.d
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import newxml.cursor;

import dom = newxml.dom;
import newxml.domimpl;
import newxml.domstring;

/++
+ Built on top of Cursor, the DOM builder adds to it the ability to
Expand All @@ -36,8 +35,7 @@ import newxml.domstring;
+ This type should not be instantiated directly. Instead, the helper function
+ `domBuilder` should be used.
+/
struct DOMBuilder(T)
if (isCursor!T)
struct DOMBuilder(T) if (isCursor!T)
{
import std.traits : ReturnType;

Expand Down Expand Up @@ -75,22 +73,23 @@ struct DOMBuilder(T)
{
switch (attr.name)
{
case "version":
document.xmlVersion = new DOMString(attr.value);
switch (attr.value) {
case "1.1":
cursor.xmlVersion = XMLVersion.XML1_1;
break;
default:
cursor.xmlVersion = XMLVersion.XML1_0;
break;
}
break;
case "standalone":
document.xmlStandalone = attr.value == "yes";
case "version":
document.xmlVersion = attr.value;
switch (attr.value)
{
case "1.1":
cursor.xmlVersion = XMLVersion.XML1_1;
break;
default:
cursor.xmlVersion = XMLVersion.XML1_0;
break;
}
break;
case "standalone":
document.xmlStandalone = attr.value == "yes";
break;
default:
break;
}
}
}
Expand Down Expand Up @@ -180,7 +179,9 @@ struct DOMBuilder(T)

auto cur = createCurrent;
if (cur)
{
currentNode.appendChild(createCurrent);
}

already_built = true;
}
Expand All @@ -207,65 +208,68 @@ struct DOMBuilder(T)
return next();
}

private NodeType createCurrent()
// TODO: handling of system (external) entities
private NodeType createCurrent() // TODO: handling of system (external) entities
{
switch (cursor.kind)
{

// XMLKind.elementEnd is needed for empty tags: <tag></tag>
case XMLKind.elementEnd:
case XMLKind.elementStart:
case XMLKind.elementEmpty:
/* DOMImplementation.Element elem = cursor.prefix.length ?
document.createElementNS(new DOMString(cursor.prefix), new DOMString(cursor.localName)) :
document.createElement(new DOMString(cursor.name)); */
DOMImplementation.Element elem = document.createElement(new DOMString(cursor.name));
foreach (attr; cursor.attributes)
{
/*if (attr.prefix.length)
case XMLKind.elementEnd:
case XMLKind.elementStart:
case XMLKind.elementEmpty:
/* DOMImplementation.Element elem = cursor.prefix.length ?
document.createElementNS(cursor.prefix, cursor.localName) :
document.createElement(cursor.name); */
DOMImplementation.Element elem = document.createElement(cursor.name);
foreach (attr; cursor.attributes)
{
/*if (attr.prefix.length)
{
elem.setAttributeNS(new DOMString(attr.prefix), new DOMString(attr.localName),
new DOMString(attr.value));
elem.setAttributeNS(attr.prefix, attr.localName,
attr.value);
}
else
{*/
elem.setAttribute(new DOMString(attr.name), new DOMString(attr.value));
//}
}
return elem;
case XMLKind.text:
return document.createTextNode(new DOMString(cursor.content));
case XMLKind.cdata:
return document.createCDATASection(new DOMString(cursor.content));
case XMLKind.processingInstruction:
return document.createProcessingInstruction(new DOMString(cursor.name), new DOMString(cursor.content));
case XMLKind.comment:
return document.createComment(new DOMString(cursor.content));
case XMLKind.dtdStart, XMLKind.dtdEmpty:
docType = domImpl.createDocumentType(new DOMString(cursor.name), new DOMString(), new DOMString());
document.doctype = docType;
return null;
case XMLKind.entityDecl:
docType.createEntity(new DOMString(cursor.name), new DOMString(cursor.content));
cursor.chrEntities[cursor.name] = cursor.content;
return null;
default:
return null;
elem.setAttribute(attr.name, attr.value);
//}
}
return elem;
case XMLKind.text:
return document.createTextNode(cursor.content);
case XMLKind.cdata:
return document.createCDATASection(cursor.content);
case XMLKind.processingInstruction:
return document.createProcessingInstruction(cursor.name,
cursor.content);
case XMLKind.comment:
return document.createComment(cursor.content);
case XMLKind.dtdStart, XMLKind.dtdEmpty:
docType = domImpl.createDocumentType(cursor.name, "", "");
document.doctype = docType;
return null;
case XMLKind.entityDecl:
docType.createEntity(cursor.name, cursor.content);
cursor.chrEntities[cursor.name] = cursor.content;
return null;
default:
return null;
}
}

/++
+ Returns the Document being built by this builder.
+/
auto getDocument() { return document; }
auto getDocument()
{
return document;
}
}

/++
+ Instantiates a suitable `DOMBuilder` on top of the given `cursor` and `DOMImplementation`.
+/
auto domBuilder(CursorType)(auto ref CursorType cursor, DOMImplementation domimpl)
if (isCursor!CursorType)
if (isCursor!CursorType)
{
auto res = DOMBuilder!(CursorType)(domimpl);
res.cursor = cursor;
Expand All @@ -282,7 +286,6 @@ unittest
import newxml.parser;
import newxml.cursor;
import domimpl = newxml.domimpl;


alias DOMImpl = domimpl.DOMImplementation;

Expand All @@ -299,30 +302,25 @@ unittest
</aaa>
};

auto builder =
xml
.lexer
.parser
.cursor
.domBuilder(new DOMImpl());
auto builder = xml.lexer.parser.cursor.domBuilder(new DOMImpl());

builder.setSource(xml);
builder.buildRecursive;
dom.Document doc = builder.getDocument;

assert(doc.getElementsByTagName(new DOMString("ccc")).length == 1);
assert(doc.documentElement.getAttribute(new DOMString("myattr")));
assert(doc.documentElement.getAttribute(new DOMString("myattr")) == "something");
assert(doc.documentElement.getAttribute(new DOMString("xmlns:myns")));
assert(doc.documentElement.getAttribute(new DOMString("xmlns:myns")) == "something");
dom.Element e1 = cast(dom.Element)doc.firstChild;
assert(doc.getElementsByTagName("ccc").length == 1);
assert(doc.documentElement.getAttribute("myattr"));
assert(doc.documentElement.getAttribute("myattr") == "something");
assert(doc.documentElement.getAttribute("xmlns:myns"));
assert(doc.documentElement.getAttribute("xmlns:myns") == "something");
dom.Element e1 = cast(dom.Element) doc.firstChild;
assert(e1.nodeName == "aaa");
dom.Element e2 = cast(dom.Element)e1.firstChild();
dom.Element e2 = cast(dom.Element) e1.firstChild();
assert(e2.nodeName == "myns:bbb");
dom.Comment c1 = cast(dom.Comment)e2.firstChild;
dom.Comment c1 = cast(dom.Comment) e2.firstChild;
assert(c1.data == " lol ");
dom.Text t1 = cast(dom.Text)e2.lastChild;
//Issue: Extra whitespace isn't dropped between and after words when dropWhiteSpace is enabled in
dom.Text t1 = cast(dom.Text) e2.lastChild;
//Issue: Extra whitespace isn't dropped between and after words when dropWhiteSpace is enabled in
//assert(t1.data == "Lots of Text! On multiple lines!", t1.data.transcodeToUTF8);

}
Expand All @@ -337,13 +335,7 @@ unittest
alias DOMImplType = domimpl.DOMImplementation;

auto xml = `<?xml version="1.0" encoding="UTF-8"?><tag></tag>`;
auto builder =
xml
.lexer
.parser
.cursor
.copyingCursor
.domBuilder(new DOMImplType());
auto builder = xml.lexer.parser.cursor.copyingCursor.domBuilder(new DOMImplType());

builder.setSource(xml);
builder.buildRecursive;
Expand Down
Loading

0 comments on commit 2c17e0e

Please sign in to comment.