123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 |
- /*
- * Copyright (c) 2005, The haXe Project Contributors
- * All rights reserved.
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
- * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
- * DAMAGE.
- */
- import flash.xml.XML;
- import flash.xml.XMLList;
- enum XmlType {
- }
- @:core_api 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 Prolog(default,null) : XmlType;
- public static var Document(default,null) : XmlType;
- public var nodeType(default,null) : XmlType;
- public var nodeName(getNodeName,setNodeName) : String;
- public var nodeValue(getNodeValue,setNodeValue) : String;
- public var parent(getParent,null) : Xml;
- var _map : flash.utils.Dictionary;
- 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( null, root, Xml.Document );
- }
- private function new() : Void {}
- public static function createElement( name : String ) : Xml {
- return wrap( null, new flash.xml.XML("<"+name+"/>"), Xml.Element );
- }
- public static function createPCData( data : String ) : Xml {
- XML.ignoreWhitespace = false;
- return wrap( null, new flash.xml.XML(data), Xml.PCData );
- }
- public static function createCData( data : String ) : Xml {
- return wrap( null, new flash.xml.XML("<![CDATA["+data+"]]>"), Xml.CData );
- }
- public static function createComment( data : String ) : Xml {
- XML.ignoreComments = false;
- return wrap( null, new flash.xml.XML("<!--"+data+"-->"), Xml.Comment );
- }
- public static function createDocType( data : String ) : Xml {
- return wrap( null, new flash.xml.XML("<!DOCTYPE "+data+">"), Xml.DocType );
- }
- public static function createProlog( data : String ) : Xml {
- XML.ignoreProcessingInstructions = false;
- return wrap( null, new flash.xml.XML("<?"+data+"?>"), Xml.Prolog );
- }
- public static function createDocument() : Xml {
- return wrap( null, 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.Prolog;
- case "comment":
- return Xml.Comment;
- default :
- throw "unimplemented node type: " + node.nodeType;
- }
- return null;
- }
- private function getNodeName() : String {
- if( nodeType != Xml.Element )
- throw "bad nodeType";
- var ns = _node.namespace();
- return (ns.prefix == "") ? _node.localName() : ns.prefix+":"+_node.localName();
- }
- private function setNodeName( 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 getNodeValue() : 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 setNodeValue( 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 = createProlog(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;
- untyped _map[_node] = this;
- return v;
- }
- private function getParent() :Xml {
- return wrap( _map, _node.parent() );
- }
- private static function wrap( map : flash.utils.Dictionary, node : XML, ?type : XmlType ) : Xml {
- if( map == null )
- map = new flash.utils.Dictionary();
- var x : Xml = untyped map[node];
- if( x == null ) {
- x = new Xml();
- x._node = node;
- x._map = map;
- x.nodeType = (type != null) ? type : getNodeType( node );
- untyped map[node] = x;
- }
- return x;
- }
- private function wraps( xList : XMLList ) : Array<Xml> {
- var out = new Array<Xml>();
- for( i in 0...xList.length() )
- out.push( wrap(_map,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;
- return {
- hasNext : function(){
- return cur < names.length;
- },
- next : function(){
- return attributes[Std.parseInt(names[cur++])].name();
- }
- }
- }
- public function iterator() : Iterator<Xml> {
- var children:XMLList = _node.children();
- if( children == null )
- throw "bad nodetype";
- 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> {
- var elements:XMLList = _node.elements();
- if( elements == null )
- throw "bad nodetype";
- 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> {
- var ns = name.split(":");
- var elements:XMLList;
- if( ns.length == 1 )
- elements = _node.elements(name);
- else
- elements = _node.elements();
- if( elements == null )
- throw "bad nodetype";
- 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 {
- var children:XMLList = _node.children();
- if( children == null )
- throw "bad nodetype";
- if( children.length() == 0 )
- return null;
- return wrap( _map, children[0] );
- }
- public function firstElement() : Xml {
- var elements:XMLList = _node.elements();
- if( elements == null )
- throw "bad nodetype";
- if( elements.length() == 0 )
- return null;
- return wrap( _map, elements[0] );
- }
- public function addChild( x : Xml ) : Void {
- var children:XMLList = _node.children();
- if( children == null )
- throw "bad nodetype";
- _node.appendChild(x._node);
- }
- public function removeChild( x : Xml ) : Bool {
- var children:XMLList = _node.children();
- if( children == null )
- throw "bad nodetype";
- 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 {
- var children:XMLList = _node.children();
- if( children == null )
- throw "bad nodetype";
- 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";
- Prolog = "prolog";
- Document = "document";
- }
- }
|