[XML-SIG] javadom.py
Lars Marius Garshol
larsga@garshol.priv.no
23 Mar 2000 18:14:05 +0100
Here is my first attempt at javadom.py. If I get permission to do so
I will check it into CVS, but for the moment I'm only posting it here.
Note that it's still pretty rough and hasn't seen all that much testing.
One unsettled question (for me) is where to put the various DOM
constants and how to name the get/set methods. I've mimicked PyDOM,
but have since seen that 4DOM does it differently. Has it been
decided which interface 4DOM will have when it's integrated into the
XML-SIG package?
# An adapter for Java DOM implementations that makes it possible to
# access them through the same interface as the Python DOM
# implementation.
# For now based on Sun's Java Project X.
# Todo:
# - implement remaining Python parts of NodeList and NamedNodeMap
# - more 4DOM-like interface? support _get_* ?
# - make a test suite
# - support more DOM implementations
# - find a scheme for doing this
# - support level 2
# - get rid of FIXMEs
import string
def filetourl(file):
# A Python port of James Clark's fileToURL from XMLTest.java.
from java.io import File
from java.net import URL
from java.lang import System
file = File(file).getAbsolutePath()
sep = System.getProperty("file.separator")
if sep != None and len(sep) == 1:
file = file.replace(sep[0], '/')
if len(file) > 0 and file[0] != '/':
file = '/' + file
return URL('file', None, file).toString()
def createDocument():
from com.sun.xml.tree import XmlDocument
return Document(XmlDocument())
def buildDocumentString(string):
from com.sun.xml.tree import XmlDocumentBuilder
return Document(XmlDocumentBuilder.createXmlDocument(string))
def buildDocumentUrl(url):
from com.sun.xml.tree import XmlDocument
return Document(XmlDocument.createXmlDocument(url))
def buildDocumentFile(filename):
return buildDocumentUrl(filetourl(filename))
# ===== Utilities
def _wrap_node(node):
if node == None:
return None
return NODE_CLASS_MAP[node.getNodeType()] (node)
# ===== Constants
ELEMENT_NODE = 1
ATTRIBUTE_NODE = 2
TEXT_NODE = 3
CDATA_SECTION_NODE = 4
ENTITY_REFERENCE_NODE = 5
ENTITY_NODE = 6
PROCESSING_INSTRUCTION_NODE = 7
COMMENT_NODE = 8
DOCUMENT_NODE = 9
DOCUMENT_TYPE_NODE = 10
DOCUMENT_FRAGMENT_NODE = 11
NOTATION_NODE = 12
# ===== DOMImplementation
class DOMImplementation:
def __init__(self, impl):
self._impl = impl
def hasFeature(self, feature, version):
if version == None or version == "1.0":
return string.lower(feature) == "xml" and \
self._impl.hasFeature(feature, version)
else:
return 0
def __repr__(self):
return "<DOMImplementation javadom.py, using '%s'>" % self._impl
# ===== Node
class Node:
def __init__(self, impl):
self._impl = impl
# attributes
def get_nodeName(self):
return self._impl.getNodeName()
def get_nodeValue(self):
return self._impl.getNodeValue()
def get_nodeType(self):
return self._impl.getNodeType()
def get_parentNode(self):
return _wrap_node(self._impl.getParentNode())
def get_childNodes(self):
children = self._impl.getChildNodes()
if children is None:
return children
else:
return NodeList(children)
def get_firstChild(self):
return _wrap_node(self._impl.getFirstChild())
def get_lastChild(self):
return _wrap_node(self._impl.getLastChild())
def get_previousSibling(self):
return _wrap_node(self._impl.getPreviousSibling())
def get_nextSibling(self):
return _wrap_node(self._impl.getNextSibling())
def get_ownerDocument(self):
return _wrap_node(self._impl.getOwnerDocument())
def get_attributes(self):
atts = self._impl.getAttributes()
if atts is None:
return None
else:
return NamedNodeMap(atts)
# methods
def insertBefore(self, new, neighbour):
self._impl.insertBefore(new._impl, neighbour._impl)
def replaceChild(self, new, old):
self._impl.replaceChild(new._impl, old._impl)
return old
def removeChild(self, old):
self._impl.removeChild(old._impl)
return old
def appendChild(self, new):
self._impl.appendChild(new._impl)
def hasChildNodes(self):
return self._impl.hasChildNodes()
def cloneNode(self):
return _wrap_node(self._impl.cloneNode())
# attribute access
def __getattr__(self, name):
if name[ :4] != "get_" and hasattr(self, "get_" + name):
return getattr(self, "get_" + name) ()
else:
raise AttributeError(name)
def __setattr__(self, name, value):
if name[ :4] != "set_" and hasattr(self, "set_" + name):
getattr(self, "set_" + name) (value)
else:
raise AttributeError(name)
# ===== Document
class Document(Node):
# methods
def createTextNode(self, data):
return Text(self._impl.createTextNode(data))
def createEntityReference(self, ):
return EntityReference(self._impl.createEntityReference())
def createElement(self, name):
return Element(self._impl.createElement(name))
def createDocumentFragment(self):
return DocumentFragment(self._impl.createDocumentFragment())
def createComment(self, data):
return Comment(self._impl.createComment(data))
def createCDATASection(self, data):
return CDATASection(self._impl.createCDATASection(data))
def createProcessingInstruction(self, target, data):
return ProcessingInstruction(self._impl.createProcessingInstruction(target, data))
def createAttribute(self, name):
return Attr(self._impl.createAttribute(name))
def getElementsByTagName(self, name):
return NodeList(self._impl.getElementsByTagName(name))
# attributes
def get_doctype(self):
return self._impl.getDoctype()
def get_implementation(self):
return DOMImplementation(self._impl.getImplementation())
def get_documentElement(self):
return _wrap_node(self._impl.getDocumentElement())
def __repr__(self):
docelm = self._impl.getDocumentElement()
if docelm:
return "<Document with root '%s'>" % docelm.getTagName()
else:
return "<Document with no root>"
# ===== Element
class Element(Node):
def __init__(self, impl):
Node.__init__(self, impl)
self.get_tagName = self._impl.getTagName
self.getAttribute = self._impl.getAttribute
self.setAttribute = self._impl.setAttribute
self.removeAttribute = self._impl.removeAttribute
self.normalize = self._impl.normalize
def getAttributeNode(self, name):
return Attr(self._impl.getAttributeNode(name))
def setAttributeNode(self, attr):
self._impl.setAttributeNode(attr._impl)
def removeAttributeNode(self, attr):
self._impl.removeAttributeNode(attr._impl)
def getElementsByTagName(self, name):
return NodeList(self._impl.getElementsByTagName(name))
def __repr__(self):
return "<Element '%s' with %d attributes and %d children>" % \
(self._impl.getTagName(),
self._impl.getAttributes().getLength(),
self._impl.getChildNodes().getLength())
# ===== CharacterData
class CharacterData(Node):
def __init__(self, impl):
Node.__init__(self, impl)
self.get_data = self._impl.getData
self.set_data = self._impl.setData
self.get_length = self._impl.getLength
self.substringData = self._impl.substringData
self.appendData = self._impl.appendData
self.insertData = self._impl.insertData
self.deleteData = self._impl.deleteData
self.replaceData = self._impl.replaceData
# ===== Comment
class Comment(CharacterData):
def __repr__(self):
return "<Comment of length %d>" % self.getLength()
# ===== ProcessingInstruction
class ProcessingInstruction(Node):
def __init__(self, impl):
Node.__init__(self, impl)
self.get_target = self._impl.getTarget
self.get_data = self._impl.getData
self.set_data = self._impl.setData
def __repr__(self):
return "<PI with target '%s'>" % self._impl.getTarget()
# ===== Text
class Text(CharacterData):
def splitText(self, offset):
return Text(self._impl.splitText(offset))
def __repr__(self):
return "<Text of length %d>" % self._impl.getLength()
# ===== CDATASection
class CDATASection(Text):
def __repr__(self):
return "<CDATA section of length %d>" % self._impl.getLength()
# ===== Attr
class Attr(Node):
def __init__(self, impl):
Node.__init__(self, impl)
self.get_name = self._impl.getName
self.get_specified = self._impl.getSpecified
self.get_value = self._impl.setValue
self.set_value = self._impl.setValue
def __repr__(self):
return "<Attr '%s'>" % self._impl.getName()
# ===== EntityReference
class EntityReference(Node):
def __repr__(self):
return "<EntityReference '%s'>" % self.getNodeName()
# ===== DocumentType
class DocumentType(Node):
def __init__(self, impl):
Node.__init__(self, impl)
self.get_name = self._impl.getName
def get_entities(self):
return NamedNodeMap(self._impl.getEntities())
def get_notations(self):
return NamedNodeMap(self._impl.getNotations())
def __repr__(self):
return "<DocumentType '%s'>" % self._impl.getNodeName()
# ===== Notation
class Notation(Node):
def __init__(self, impl):
Node.__init__(self, impl)
self.get_publicId = self._impl.getPublicId
self.get_systemId = self._impl.getSystemId
def __repr__(self):
return "<Notation '%s'>" % self._impl.getNodeName()
# ===== Entity
class Entity(Node):
def __init__(self, impl):
Node.__init__(self, impl)
self.get_publicId = self._impl.getPublicId
self.get_systemId = self._impl.getSystemId
self.get_notationName = self._impl.getNotationName
def __repr__(self):
return "<Entity '%s'>" % self._impl.getNodeName()
# ===== DocumentFragment
class DocumentFragment(Node):
def __repr__(self):
return "<DocumentFragment>"
# ===== NodeList
class NodeList:
def __init__(self, impl):
self._impl = impl
self.__len__ = self._impl.getLength
self.get_length = self._impl.getLength
self.item = self._impl.item
# Python list methods
def __getitem__(self, ix):
node = self._impl.item(ix)
if node is None:
raise IndexError
else:
return _wrap_node(node)
def __setitem__(self, ix, item):
raise TypeError, "NodeList instances don't support item assignment"
def __delitem__(self, ix, item):
raise TypeError, "NodeList instances don't support item deletion"
def __setslice__(self, i, j, list):
raise TypeError, "NodeList instances don't support slice assignment"
def __delslice__(self, i, j):
raise TypeError, "NodeList instances don't support slice deletion"
def append(self, item):
raise TypeError, "NodeList instances don't support .append()"
def insert(self, i, item):
raise TypeError, "NodeList instances don't support .insert()"
def pop(self, i=-1):
raise TypeError, "NodeList instances don't support .pop()"
def remove(self, item):
raise TypeError, "NodeList instances don't support .remove()"
def reverse(self):
raise TypeError, "NodeList instances don't support .reverse()"
def sort(self, *args):
raise TypeError, "NodeList instances don't support .sort()"
def __repr__(self):
return "<NodeList [ %s ]>" % string.join(map(repr, self), ", ")
# FIXME: getslice, add, radd, mul, rmul, count, index
# ===== NamedNodeMap
class NamedNodeMap:
def __init__(self, impl):
self._impl = impl
self.get_length = self._impl.getLength
self.__len__ = self._impl.getLength
def getNamedItem(self, name):
return _wrap_node(self._impl.getNamedItem(name))
def setNamedItem(self, node):
return _wrap_node(self._impl.setNamedItem(node._impl))
def removedNamedItem(self, name):
return _wrap_node(self._impl.removedNamedItem(name))
def item(self, index):
return _wrap_node(self._impl.item(index))
# Python dictionary methods
def __getitem__(self, key):
node = self._impl.getNamedItem(name)
if node is None:
raise KeyError, key
else:
return _wrap_node(node)
def get(self, key, alternative = None):
node = self._impl.getNamedItem(name)
if node is None:
return alternative
else:
return _wrap_node(node)
def has_key(self, key):
return self._impl.getNamedItem(name) != None
def items(self):
list = []
for ix in range(self._impl.getLength()):
node = self._impl.item(ix)
list.append((node.getNodeName(), _wrap_node(node)))
return list
def keys(self):
list = []
for ix in range(self._impl.getLength()):
list.append(self._impl.item(ix).getNodeName())
return list
def values(self):
list = []
for ix in range(self._impl.getLength()):
list.append(_wrap_node(self._impl.item(ix)))
return list
def __repr__(self):
pairs = []
for pair in self.items():
pairs.append("'%s' : %s" % pair)
return "<NamedNodeMap { %s }>" % string.join(pairs, ", ")
# FIXME! setitem, update
# ===== Various stuff
NODE_CLASS_MAP = {
ELEMENT_NODE : Element,
ATTRIBUTE_NODE : Attr,
TEXT_NODE : Text,
CDATA_SECTION_NODE : CDATASection,
ENTITY_REFERENCE_NODE : EntityReference,
ENTITY_NODE : Entity,
PROCESSING_INSTRUCTION_NODE : ProcessingInstruction,
COMMENT_NODE : Comment,
DOCUMENT_NODE : Document,
DOCUMENT_TYPE_NODE : DocumentType,
DOCUMENT_FRAGMENT_NODE : DocumentFragment,
NOTATION_NODE : Notation
}
# ===== Self-test
if __name__ == "__main__":
doc2 = createDocument()
print doc2
print doc2.get_implementation()
root = doc2.createElement("doc")
print root
doc2.appendChild(root)
txt = doc2.createTextNode("This is a simple sample \n")
print txt
root.appendChild(txt)
print root.get_childNodes()[0]
print root.get_childNodes()
root.setAttribute("huba", "haba")
print root
print root.get_attributes()
--Lars M.