123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418 |
- /*
- * Copyright (C)2005-2019 Haxe Foundation
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- */
- package flash;
- import flash.xml.XML;
- import flash.xml.XMLList;
- extern enum XmlType {}
- typedef NativeXml = Xml;
- class Xml {
- public static var Element(default, null):XmlType;
- public static var PCData(default, null):XmlType;
- public static var CData(default, null):XmlType;
- public static var Comment(default, null):XmlType;
- public static var DocType(default, null):XmlType;
- public static var ProcessingInstruction(default, null):XmlType;
- public static var Document(default, null):XmlType;
- public var nodeType(default, null):XmlType;
- public var nodeName(get, set):String;
- public var nodeValue(get, set):String;
- public var parent(get, null):Xml;
- var _node:flash.xml.XML;
- public static function parse(str:String):Xml {
- XML.ignoreWhitespace = false;
- XML.ignoreProcessingInstructions = false;
- XML.ignoreComments = false;
- var prefix = "<__document";
- var root = null;
- while (root == null) {
- try {
- root = new flash.xml.XML(prefix + ">" + str + "</__document>");
- } catch (e:flash.errors.TypeError) {
- // if we miss a namespace, let's add it !
- var r = ~/"([^"]+)"/; // "
- if (e.errorID == 1083 && r.match(e.message)) {
- var ns = r.matched(1);
- prefix += " xmlns:" + ns + '="@' + ns + '"';
- } else
- throw e;
- }
- }
- return wrap(root, Xml.Document);
- }
- @:keep static function compare(a:Xml, b:Xml):Bool {
- return a == null ? b == null : (b == null ? false : a._node == b._node);
- }
- private function new():Void {}
- public static function createElement(name:String):Xml {
- return wrap(new flash.xml.XML("<" + name + "/>"), Xml.Element);
- }
- public static function createPCData(data:String):Xml {
- XML.ignoreWhitespace = false;
- return wrap(new flash.xml.XML(data), Xml.PCData);
- }
- public static function createCData(data:String):Xml {
- return wrap(new flash.xml.XML("<![CDATA[" + data + "]]>"), Xml.CData);
- }
- public static function createComment(data:String):Xml {
- XML.ignoreComments = false;
- return wrap(new flash.xml.XML("<!--" + data + "-->"), Xml.Comment);
- }
- public static function createDocType(data:String):Xml {
- return wrap(new flash.xml.XML("<!DOCTYPE " + data + ">"), Xml.DocType);
- }
- public static function createProcessingInstruction(data:String):Xml {
- XML.ignoreProcessingInstructions = false;
- return wrap(new flash.xml.XML("<?" + data + "?>"), Xml.ProcessingInstruction);
- }
- public static function createDocument():Xml {
- return wrap(new flash.xml.XML("<__document/>"), Xml.Document);
- }
- private static function getNodeType(node:flash.xml.XML):XmlType {
- switch (node.nodeKind()) {
- case "element":
- return Xml.Element;
- case "text":
- return Xml.PCData;
- case "processing-instruction":
- return Xml.ProcessingInstruction;
- case "comment":
- return Xml.Comment;
- default:
- throw "unimplemented node type: " + node.nodeType;
- }
- }
- private function get_nodeName():String {
- if (nodeType != Xml.Element)
- throw "bad nodeType";
- var ns = _node.namespace();
- return (ns.prefix == "") ? _node.localName() : ns.prefix + ":" + _node.localName();
- }
- private function set_nodeName(n:String):String {
- if (nodeType != Xml.Element)
- throw "bad nodeType";
- var ns = n.split(":");
- if (ns.length == 1)
- _node.setLocalName(n);
- else {
- _node.setLocalName(ns[1]);
- _node.setNamespace(_node.namespace(ns[0]));
- }
- return n;
- }
- private function get_nodeValue():String {
- var nodeType = nodeType;
- if (nodeType == Xml.Element || nodeType == Xml.Document)
- throw "bad nodeType";
- if (nodeType == Xml.Comment)
- return _node.toString().substr(4, -7);
- return _node.toString();
- }
- private function set_nodeValue(v:String):String {
- var nodeType = nodeType;
- var x = null;
- if (nodeType == Xml.Element || nodeType == Xml.Document)
- throw "bad nodeType";
- else if (nodeType == Xml.PCData)
- x = createPCData(v);
- else if (nodeType == Xml.CData)
- x = createCData(v);
- else if (nodeType == Xml.Comment)
- x = createComment(v);
- else if (nodeType == Xml.DocType)
- x = createDocType(v);
- else
- x = createProcessingInstruction(v);
- var p = _node.parent();
- if (p != null) {
- p.insertChildAfter(_node, x._node);
- var i = _node.childIndex();
- var children = p.children();
- untyped __delete__(children, Reflect.fields(children)[i]);
- }
- _node = x._node;
- return v;
- }
- private function get_parent():Xml {
- var p = _node.parent();
- return p == null ? null : wrap(p);
- }
- private static function wrap(node:XML, ?type:XmlType):Xml {
- var x = new Xml();
- x._node = node;
- x.nodeType = (type != null) ? type : getNodeType(node);
- return x;
- }
- private function wraps(xList:XMLList):Array<Xml> {
- var out = new Array<Xml>();
- for (i in 0...xList.length())
- out.push(wrap(xList[i]));
- return out;
- }
- function getAttribNS(cur:XML, ns:Array<String>):XMLList {
- var n = cur.namespace(ns[0]);
- if (n == null) {
- var parent = cur.parent();
- if (parent == null) {
- n = new flash.utils.Namespace(ns[0], "@" + ns[0]);
- cur.addNamespace(n);
- } else
- return getAttribNS(parent, ns);
- }
- return _node.attribute(new flash.utils.QName(n, ns[1]));
- }
- public function get(att:String):String {
- if (nodeType != Xml.Element)
- throw "bad nodeType";
- var ns = att.split(":");
- if (ns[0] == "xmlns") {
- var n = _node.namespace((ns[1] == null) ? "" : ns[1]);
- return (n == null) ? null : n.uri;
- }
- if (ns.length == 1) {
- if (!Reflect.hasField(_node, "@" + att))
- return null;
- return Reflect.field(_node, "@" + att);
- }
- var a = getAttribNS(_node, ns);
- return (a.length() == 0) ? null : a.toString();
- }
- public function set(att:String, value:String):Void {
- if (nodeType != Xml.Element)
- throw "bad nodeType";
- var ns = att.split(":");
- if (ns[0] == "xmlns") {
- var n = _node.namespace((ns[1] == null) ? "" : ns[1]);
- if (n != null)
- throw "Can't modify namespace";
- if (ns[1] == null)
- throw "Can't set default namespace";
- _node.addNamespace(new flash.utils.Namespace(ns[1], value));
- return;
- }
- if (ns.length == 1)
- Reflect.setField(_node, "@" + att, value);
- else {
- var a = getAttribNS(_node, ns);
- untyped a[0] = value;
- }
- }
- public function remove(att:String):Void {
- if (nodeType != Xml.Element)
- throw "bad nodeType";
- var ns = att.split(":");
- if (ns.length == 1)
- Reflect.deleteField(_node, "@" + att);
- else
- untyped __delete__(getAttribNS(_node, ns), 0);
- }
- public function exists(att:String):Bool {
- if (nodeType != Xml.Element)
- throw "bad nodeType";
- var ns = att.split(":");
- if (ns[0] == "xmlns")
- return _node.namespace((ns[1] == null) ? "" : ns[1]) != null;
- if (ns.length == 1)
- return Reflect.hasField(_node, "@" + att);
- return getAttribNS(_node, ns).length() > 0;
- }
- public function attributes():Iterator<String> {
- if (nodeType != Xml.Element)
- throw "bad nodeType";
- var attributes:XMLList = _node.attributes();
- var names = Reflect.fields(attributes);
- var cur = 0;
- var nss = _node.namespaceDeclarations();
- return {
- hasNext: function() {
- return cur < names.length + nss.length;
- },
- next: function() {
- if (cur < names.length) {
- return attributes[Std.parseInt(names[cur++])].name();
- } else {
- var ns:flash.utils.Namespace = nss[cur++ - names.length];
- return "xmlns:" + ns.prefix;
- }
- }
- }
- }
- public function iterator():Iterator<Xml> {
- if (nodeType != Xml.Element && nodeType != Xml.Document)
- throw "bad nodeType";
- var children:XMLList = _node.children();
- var wrappers:Array<Xml> = wraps(children);
- var cur = 0;
- return {
- hasNext: function() {
- return cur < wrappers.length;
- },
- next: function() {
- return wrappers[cur++];
- }
- };
- }
- public function elements():Iterator<Xml> {
- if (nodeType != Xml.Element && nodeType != Xml.Document)
- throw "bad nodeType";
- var elements:XMLList = _node.elements();
- var wrappers:Array<Xml> = wraps(elements);
- var cur = 0;
- return {
- hasNext: function() {
- return cur < wrappers.length;
- },
- next: function() {
- return wrappers[cur++];
- }
- };
- }
- public function elementsNamed(name:String):Iterator<Xml> {
- if (nodeType != Xml.Element && nodeType != Xml.Document)
- throw "bad nodeType";
- var ns = name.split(":");
- var elements:XMLList;
- if (ns.length == 1)
- elements = _node.elements(name);
- else
- elements = _node.elements();
- var wrappers:Array<Xml> = wraps(elements);
- if (ns.length != 1)
- for (w in wrappers.copy())
- if (w._node.localName() != ns[1] || w._node.namespace().prefix != ns[0])
- wrappers.remove(w);
- var cur = 0;
- return {
- hasNext: function() {
- return cur < wrappers.length;
- },
- next: function() {
- return wrappers[cur++];
- }
- };
- }
- public function firstChild():Xml {
- if (nodeType != Xml.Element && nodeType != Xml.Document)
- throw "bad nodeType";
- var children:XMLList = _node.children();
- if (children.length() == 0)
- return null;
- return wrap(children[0]);
- }
- public function firstElement():Xml {
- if (nodeType != Xml.Element && nodeType != Xml.Document)
- throw "bad nodeType";
- var elements:XMLList = _node.elements();
- if (elements.length() == 0)
- return null;
- return wrap(elements[0]);
- }
- public function addChild(x:Xml):Void {
- if (nodeType != Xml.Element && nodeType != Xml.Document)
- throw "bad nodeType";
- if (x.parent != null)
- x.parent.removeChild(x);
- var children:XMLList = _node.children();
- _node.appendChild(x._node);
- }
- public function removeChild(x:Xml):Bool {
- if (nodeType != Xml.Element && nodeType != Xml.Document)
- throw "bad nodeType";
- var children:XMLList = _node.children();
- if (_node != x._node.parent())
- return false;
- var i = x._node.childIndex();
- untyped __delete__(children, Reflect.fields(children)[i]);
- return true;
- }
- public function insertChild(x:Xml, pos:Int):Void {
- if (nodeType != Xml.Element && nodeType != Xml.Document)
- throw "bad nodeType";
- if (x.parent != null)
- x.parent.removeChild(x);
- var children:XMLList = _node.children();
- if (pos < children.length())
- _node.insertChildBefore(children[pos], x._node);
- else
- _node.appendChild(x._node);
- }
- public function toString():String {
- XML.prettyPrinting = false;
- if (nodeType == Xml.Document) {
- var str = _node.toXMLString();
- // remove <__document xmlns....>STR</__document> wrapper
- str = str.substr(str.indexOf(">") + 1);
- str = str.substr(0, str.length - 13);
- return str;
- }
- return _node.toXMLString();
- }
- static function __init__():Void
- untyped {
- Element = "element";
- PCData = "pcdata";
- CData = "cdata";
- Comment = "comment";
- DocType = "doctype";
- ProcessingInstruction = "processingInstruction";
- Document = "document";
- }
- }
|