* implement 4suite domlette support based on faik's patch

* but it cannot encode xml:lang attributes, needs a fix :(
This commit is contained in:
Eray Özkural
2005-11-10 00:53:44 +00:00
parent b81adc094e
commit abe9b75388
7 changed files with 386 additions and 15 deletions
+5 -5
View File
@@ -101,7 +101,7 @@ class LocalText(dict):
assert self.tag != ''
for key in self.iterkeys():
newnode = newNode(node, self.tag)
newnode.setAttribute('xml:lang', key)
newnode.setAttributeNS(None, 'xml:lang', key)
newtext = newTextNode(node, self[key])
newnode.appendChild(newtext)
node.appendChild(newnode)
@@ -400,7 +400,7 @@ class autoxml(oo.autosuper, oo.autoprop):
errs.append(_("autoxml.write: object validation has failed"))
raise Error(*errs)
errs = []
self.newDOM()
self.newDocument()
self.encode(self.rootNode(), errs)
if hasattr(self, 'write_hook'):
self.write_hook(errs)
@@ -423,7 +423,7 @@ class autoxml(oo.autosuper, oo.autoprop):
return getNodeAttribute(node, attr)
def writetext(node, attr, text):
#print 'write attr', attr, text
node.setAttribute(attr, text)
node.setAttributeNS(None, attr, text)
anonfuns = cls.gen_anon_basic(attr, spec, readtext, writetext)
return cls.gen_named_comp(attr, spec, anonfuns)
@@ -637,7 +637,7 @@ class autoxml(oo.autosuper, oo.autoprop):
if node and obj:
try:
#FIXME: this doesn't look pretty
classnode = node.ownerDocument.createElement(tag)
classnode = newNode(node, tag)
obj.encode(classnode, errs)
node.appendChild(classnode)
except Error:
@@ -684,7 +684,7 @@ class autoxml(oo.autosuper, oo.autoprop):
errs.append(where + _('Mandatory list empty'))
ix = 1
for node in nodes:
dummy = node.ownerDocument.createElement("Dummy")
dummy = newNode(node, "Dummy")
dummy.appendChild(node)
l.append(decode_item(dummy, errs, where + unicode("[%s]" % ix)))
#l.append(decode_item(node, errs, where + unicode("[%s]" % ix)))
+5 -2
View File
@@ -15,5 +15,8 @@ try:
zimbabwe # comment out to disable piks
from xmlextpiks import *
except:
print 'xmlext: piksemel implementation cannot be loaded, falling back to minidom'
from xmlextmdom import *
try:
from xmlextcdom import *
except:
print 'xmlext: cDomlette/piksemel implementation cannot be loaded, falling back to minidom'
from xmlextmdom import *
+203
View File
@@ -0,0 +1,203 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2005, TUBITAK/UEKAE
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#
# Authors: Eray Ozkural <eray@uludag.org.tr>
# Baris Metin <baris@uludag.org.tr
# Gurer Ozen <gurer@uludag.org.tr>
# Faik Uygur <faikuygur@gmail.com>
"""
xmlext is a helper module for accessing XML files using
xml.dom.minidom . It is a convenient wrapper for some
DOM functions, and provides path based get/add functions
as in KDE API.
function names are mixedCase for compatibility with minidom,
an 'old library'
this implementation uses cDomlette from 4suite.org
adapted from the minidom implementation by Faik Uygur.
"""
import gettext
__trans = gettext.translation('pisi', fallback=True)
_ = __trans.ugettext
import Ft
from Ft.Xml.Domlette import implementation
from Ft.Xml import ParsePath
from Ft.Xml.Domlette import NonvalidatingReader
import pisi
class XmlError(pisi.Error):
"named this way because the class if mostly used with an import *"
pass
# Document wrappers
def newDocument(tag):
# create a document and return document root
doc = implementation.createDocument(None, tag, None)
return doc.documentElement
def parse(filename):
# parse file and return document root
try:
doc = ParsePath(filename)
return doc.documentElement
except Ft.FtException, e:
raise Error(_("File '%s' has invalid XML: %s") % (filename, str(e)))
def newNode(node, tag):
return node.ownerDocument.createElementNS(None, tag)
def newTextNode(node, text):
return node.ownerDocument.createTextNode(text)
# Node related wrappers
def getNodeAttribute(node, attrname):
"""get named attribute from DOM node"""
if not node.hasAttributeNS(None, attrname):
return None
else:
return node.getAttributeNS(None, attrname)
def getChildElts(node):
"""get only child elements"""
return filter(lambda x:x.nodeType == x.ELEMENT_NODE, node.childNodes)
def getTagByName(parent, childName):
return [x for x in parent.childNodes
if x.nodeType == x.ELEMENT_NODE and x.tagName == childName]
def getNodeText(node, tagpath = ""):
"""get the first child and expect it to be text!"""
if tagpath!="":
node = getNode(node, tagpath)
try:
child = node.childNodes[0]
except IndexError:
return None
except AttributeError: # no node by that name
return None
if child.nodeType == child.TEXT_NODE:
# in any case, strip whitespaces...
return child.data.strip()
else:
raise XmlError(_("getNodeText: Expected text node, got something else!"))
def getChildText(node_s, tagpath):
"""get the text of a child at the end of a tag path"""
node = getNode(node_s, tagpath)
if not node:
return None
return getNodeText(node)
def getNode(node, tagpath):
"""returns the *first* matching node for given tag path."""
assert type(tagpath)==str
tags = tagpath.split('/')
assert len(tags)>0
# iterative code to search for the path
for tag in tags:
currentNode = None
for child in node.childNodes:
if child.nodeType == node.ELEMENT_NODE and child.tagName == tag:
currentNode = child
break
if not currentNode:
return None
else:
node = currentNode
return currentNode
def getAllNodes(node, tagPath):
"""retrieve all nodes that match a given tag path."""
#FIXME: better tag split
tags = tagPath.split('/')
if len(tags) == 0:
return []
nodeList = [node] # basis case
for tag in tags:
results = map(lambda x: getTagByName(x, tag), nodeList)
nodeList = []
for x in results:
nodeList.extend(x)
pass # emacs indentation error, keep it here
if len(nodeList) == 0:
return []
return nodeList
def createTagPath(node, tags):
"""create new child at the end of a tag chain starting from node
no matter what"""
if len(tags)==0:
return node
dom = node.ownerDocument
for tag in tags:
node = node.appendChild(dom.createElementNS(None, tag))
return node
def addTagPath(node, tags, newnode=None):
"""add newnode at the end of a tag chain, smart one"""
node = createTagPath(node, tags)
if newnode: # node to add specified
node.appendChild(newnode)
return node
def addNode(node, tagpath, newnode = None, branch=True):
"""add a new node at the end of the tree and returns it
if newnode is given adds that node, too."""
assert type(tagpath)==str
tags = []
if tagpath != "":
tags = tagpath.split('/') # tag chain
else:
addTagPath(node, [], newnode)
return node #FIXME: is this correct!?!?
assert len(tags)>0 # we want a chain
# iterative code to search for the path
if branch:
rem = 1
else:
rem = 0
while len(tags) > rem:
tag = tags.pop(0)
nodeList = getTagByName(node, tag)
if len(nodeList) == 0: # couldn't find
tags.insert(0, tag) # put it back in
return addTagPath(node, tags, newnode)
else:
node = nodeList[len(nodeList)-1] # discard other matches
else:
# had only one tag..
return addTagPath(node, tags, newnode)
return node
def addText(node, tagPath, text, branch = True):
newnode = newTextNode(node, text)
return addNode(node, tagPath, newnode, branch = branch)
+6 -4
View File
@@ -13,8 +13,10 @@
try:
horagata # comment out to disable piks
from xmlextpiks import *
from xmlfilepiks import *
#from xmlfilepiks import *
except:
print 'xmlfile: piksemel implementation cannot be loaded, falling back to minidom'
from xmlfilemdom import *
try:
from xmlfilecdom import *
except:
print 'xmlext: cDomlette/piksemel implementation cannot be loaded, falling back to minidom'
from xmlfilemdom import *
+163
View File
@@ -0,0 +1,163 @@
# -*- coding: utf-8 -*-
#
# Copyright (C) 2005, TUBITAK/UEKAE
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 2 of the License, or (at your option)
# any later version.
#
# Please read the COPYING file.
#
# Authors: Eray Ozkural <eray@uludag.org.tr>
# Baris Metin <baris@uludag.org.tr
# Faik Uygur <faikuygur@gmail.com>
"""
XmlFile class further abstracts a dom object using the
high-level dom functions provided in xmlext module (and sorely lacking
in xml.dom :( )
function names are mixedCase for compatibility with minidom,
an 'old library'
this implementation uses cDomlette from 4suite.org
adapted from the minidom implementation by Faik Uygur.
"""
import gettext
__trans = gettext.translation('pisi', fallback=True)
_ = __trans.ugettext
import codecs
import Ft
from Ft.Xml.Domlette import implementation
from Ft.Xml.Domlette import NonvalidatingReader
from Ft.Xml import Parse, ParsePath
from Ft.Xml.Domlette import Print, PrettyPrint
import pisi
class Error(pisi.Error):
"named this way because the class if mostly used with an import *"
pass
class XmlFile(object):
"""A class to help reading and writing an XML file"""
def __init__(self, tag):
self.rootTag = tag
self.newDocument()
def newDocument(self):
"""clear DOM"""
self.doc = implementation.createDocument(None, self.rootTag, None)
def unlink(self):
"""deallocate DOM structure"""
#del self.doc
self.doc = None # why?
def rootNode(self):
"""returns root document element"""
return self.doc.documentElement
def readxml(self, path):
try:
self.doc = ParsePath(path)
return self.doc.documentElement
except Ft.FtException, e:
raise Error(_("File '%s' has invalid XML:") % (path, str(e)) )
def writexml(self, path):
f = file(path, 'w')
Print(self.rootNode(), stream = f)
f.close()
def verifyRootTag(self):
actual_roottag = self.rootNode().tagName
if actual_roottag != self.rootTag:
raise Error(_("Root tagname %s not identical to %s as expected") %
(actual_roottag, self.rootTag) )
# construction helpers
def newNode(self, tag):
return self.dom.createElementNS(None, tag)
def newTextNode(self, text):
return self.dom.createTextNode(text)
def newAttribute(self, attr):
return self.dom.createAttribute(attr)
# read helpers
def getNode(self, tagPath = ""):
"""returns the *first* matching node for given tag path."""
self.verifyRootTag()
return getNode(self.dom.documentElement, tagPath)
def getNodeText(self, tagPath):
"""returns the text of *first* matching node for given tag path."""
node = self.getNode(tagPath)
if not node:
return None
return getNodeText(node)
def getAllNodes(self, tagPath):
"""returns all nodes matching a given tag path."""
self.verifyRootTag()
return getAllNodes(self.dom.documentElement, tagPath)
def getChildren(self, tagpath):
""" returns the children of the given path"""
node = self.getNode(tagpath)
return node.childNodes
# get only elements of a given type
#FIXME: this doesn't work
def getChildrenWithType(self, tagpath, type):
""" returns the children of the given path, only with given type """
node = self.getNode(tagpath)
return filter(lambda x:x.nodeType == type, node.childNodes)
# get only child elements
def getChildElts(self, tagpath):
""" returns the children of the given path, only with given type """
node = self.getNode(tagpath)
try:
return filter(lambda x:x.nodeType == x.ELEMENT_NODE,
node.childNodes)
except AttributeError:
return None
# write helpers
def addNode(self, tagPath, newnode = None):
"this adds the newnode under given tag path"
self.verifyRootTag()
return addNode(self.dom.documentElement, tagPath, newnode)
def addNodeUnder(self, node, tagPath, newnode = None):
"this adds the new stuff under node and then following tag path"
self.verifyRootTag()
return addNode(node, tagPath, newnode)
def addChild(self, newnode):
"add a new child node right under root element document"
self.dom.documentElement.appendChild(newnode)
def addText(self, node, text):
"add text to node"
node.appendChild(self.newTextNode(text))
def addTextNode(self, tagPath, text):
"add a text node with given tag path"
node = self.addNode(tagPath, self.newTextNode(text))
return node
def addTextNodeUnder(self, node, tagPath, text):
"add a text node under given node with tag path (phew)"
return self.addNodeUnder(node, tagPath, self.newTextNode(text))
+2 -2
View File
@@ -43,9 +43,9 @@ class XmlFile(object):
def __init__(self, tag):
self.rootTag = tag
self.newDOM()
self.newDocument()
def newDOM(self):
def newDocument(self):
"""clear DOM"""
impl = mdom.getDOMImplementation()
self.dom = impl.createDocument(None, self.rootTag, None)
+2 -2
View File
@@ -36,9 +36,9 @@ class XmlFile(object):
def __init__(self, tag):
self.rootTag = tag
self.newDOM()
self.newDocument()
def newDOM(self):
def newDocument(self):
"""clear DOM"""
self.doc = newDocument(self.rootTag)