final XML ecmaToXml(Object object) { // See ECMA357 10.3 if (object == null || object == Undefined.instance) { throw ScriptRuntime.typeError("Cannot convert " + object + " to XML"); } if (object instanceof XML) return (XML) object; if (object instanceof XMLList) { XMLList list = (XMLList) object; if (list.getXML() != null) { return list.getXML(); } else { throw ScriptRuntime.typeError("Cannot convert list of >1 element to XML"); } } // TODO Technically we should fail on anything except a String, Number or Boolean // See ECMA357 10.3 // Extension: if object is a DOM node, use that to construct the XML // object. if (object instanceof Wrapper) { object = ((Wrapper) object).unwrap(); } if (object instanceof org.w3c.dom.Node) { org.w3c.dom.Node node = (org.w3c.dom.Node) object; return newXML(XmlNode.createElementFromNode(node)); } // Instead we just blindly cast to a String and let them convert anything. String s = ScriptRuntime.toString(object); // TODO Could this get any uglier? if (s.length() > 0 && s.charAt(0) == '<') { return parse(s); } else { return newXML(XmlNode.createText(options, s)); } }
@Override void putXMLProperty(XMLName xmlName, Object value) { // Log("put property: " + name); // Special-case checks for undefined and null if (value == null) { value = "null"; } else if (value instanceof Undefined) { value = "undefined"; } if (length() > 1) { throw ScriptRuntime.typeError("Assignment to lists with more than one item is not supported"); } else if (length() == 0) { // Secret sauce for super-expandos. // We set an element here, and then add ourselves to our target. if (targetObject != null && targetProperty != null && targetProperty.getLocalName() != null && targetProperty.getLocalName().length() > 0) { // Add an empty element with our targetProperty name and // then set it. XML xmlValue = newTextElementXML(null, targetProperty, null); addToList(xmlValue); if (xmlName.isAttributeName()) { setAttribute(xmlName, value); } else { XML xml = item(0); xml.putXMLProperty(xmlName, value); // Update the list with the new item at location 0. replace(0, item(0)); } // Now add us to our parent XMLName name2 = XMLName.formProperty( targetProperty.getNamespace().getUri(), targetProperty.getLocalName()); targetObject.putXMLProperty(name2, this); replace(0, targetObject.getXML().getLastXmlChild()); } else { throw ScriptRuntime.typeError("Assignment to empty XMLList without targets not supported"); } } else if (xmlName.isAttributeName()) { setAttribute(xmlName, value); } else { XML xml = item(0); xml.putXMLProperty(xmlName, value); // Update the list with the new item at location 0. replace(0, item(0)); } }
private XML parse(String frag) { try { return newXML( XmlNode.createElement( options, getDefaultNamespaceURI(Context.getCurrentContext()), frag)); } catch (SAXException e) { throw ScriptRuntime.typeError("Cannot parse XML: " + e.getMessage()); } }
private static RuntimeException badXMLName(Object value) { String msg; if (value instanceof Number) { msg = "Can not construct XML name from number: "; } else if (value instanceof Boolean) { msg = "Can not construct XML name from boolean: "; } else if (value == Undefined.instance || value == null) { msg = "Can not construct XML name from "; } else { throw new IllegalArgumentException(value.toString()); } return ScriptRuntime.typeError(msg + ScriptRuntime.toString(value)); }
final XMLList newXMLListFrom(Object inputObject) { XMLList rv = newXMLList(); if (inputObject == null || inputObject instanceof Undefined) { return rv; } else if (inputObject instanceof XML) { XML xml = (XML) inputObject; rv.getNodeList().add(xml); return rv; } else if (inputObject instanceof XMLList) { XMLList xmll = (XMLList) inputObject; rv.getNodeList().add(xmll.getNodeList()); return rv; } else { String frag = ScriptRuntime.toString(inputObject).trim(); if (!frag.startsWith("<>")) { frag = "<>" + frag + "</>"; } frag = "<fragment>" + frag.substring(2); if (!frag.endsWith("</>")) { throw ScriptRuntime.typeError("XML with anonymous tag missing end anonymous tag"); } frag = frag.substring(0, frag.length() - 3) + "</fragment>"; XML orgXML = newXMLFromJs(frag); // Now orphan the children and add them to our XMLList. XMLList children = orgXML.children(); for (int i = 0; i < children.getNodeList().length(); i++) { // Copy here is so that they'll be orphaned (parent() will be undefined) rv.getNodeList().add(((XML) children.item(i).copy())); } return rv; } }
/* TODO: Can this can be replaced by ecmaToXml below? */ final XML newXMLFromJs(Object inputObject) { String frag; if (inputObject == null || inputObject == Undefined.instance) { frag = ""; } else if (inputObject instanceof XMLObjectImpl) { // todo: faster way for XMLObjects? frag = ((XMLObjectImpl) inputObject).toXMLString(); } else { frag = ScriptRuntime.toString(inputObject); } if (frag.trim().startsWith("<>")) { throw ScriptRuntime.typeError("Invalid use of XML object anonymous tags <></>."); } if (frag.indexOf("<") == -1) { // Solo text node return newXML(XmlNode.createText(options, frag)); } return parse(frag); }