* implement 4suite domlette support based on faik's patch
* but it cannot encode xml:lang attributes, needs a fix :(
This commit is contained in:
+5
-5
@@ -101,7 +101,7 @@ class LocalText(dict):
|
|||||||
assert self.tag != ''
|
assert self.tag != ''
|
||||||
for key in self.iterkeys():
|
for key in self.iterkeys():
|
||||||
newnode = newNode(node, self.tag)
|
newnode = newNode(node, self.tag)
|
||||||
newnode.setAttribute('xml:lang', key)
|
newnode.setAttributeNS(None, 'xml:lang', key)
|
||||||
newtext = newTextNode(node, self[key])
|
newtext = newTextNode(node, self[key])
|
||||||
newnode.appendChild(newtext)
|
newnode.appendChild(newtext)
|
||||||
node.appendChild(newnode)
|
node.appendChild(newnode)
|
||||||
@@ -400,7 +400,7 @@ class autoxml(oo.autosuper, oo.autoprop):
|
|||||||
errs.append(_("autoxml.write: object validation has failed"))
|
errs.append(_("autoxml.write: object validation has failed"))
|
||||||
raise Error(*errs)
|
raise Error(*errs)
|
||||||
errs = []
|
errs = []
|
||||||
self.newDOM()
|
self.newDocument()
|
||||||
self.encode(self.rootNode(), errs)
|
self.encode(self.rootNode(), errs)
|
||||||
if hasattr(self, 'write_hook'):
|
if hasattr(self, 'write_hook'):
|
||||||
self.write_hook(errs)
|
self.write_hook(errs)
|
||||||
@@ -423,7 +423,7 @@ class autoxml(oo.autosuper, oo.autoprop):
|
|||||||
return getNodeAttribute(node, attr)
|
return getNodeAttribute(node, attr)
|
||||||
def writetext(node, attr, text):
|
def writetext(node, attr, text):
|
||||||
#print 'write attr', 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)
|
anonfuns = cls.gen_anon_basic(attr, spec, readtext, writetext)
|
||||||
return cls.gen_named_comp(attr, spec, anonfuns)
|
return cls.gen_named_comp(attr, spec, anonfuns)
|
||||||
|
|
||||||
@@ -637,7 +637,7 @@ class autoxml(oo.autosuper, oo.autoprop):
|
|||||||
if node and obj:
|
if node and obj:
|
||||||
try:
|
try:
|
||||||
#FIXME: this doesn't look pretty
|
#FIXME: this doesn't look pretty
|
||||||
classnode = node.ownerDocument.createElement(tag)
|
classnode = newNode(node, tag)
|
||||||
obj.encode(classnode, errs)
|
obj.encode(classnode, errs)
|
||||||
node.appendChild(classnode)
|
node.appendChild(classnode)
|
||||||
except Error:
|
except Error:
|
||||||
@@ -684,7 +684,7 @@ class autoxml(oo.autosuper, oo.autoprop):
|
|||||||
errs.append(where + _('Mandatory list empty'))
|
errs.append(where + _('Mandatory list empty'))
|
||||||
ix = 1
|
ix = 1
|
||||||
for node in nodes:
|
for node in nodes:
|
||||||
dummy = node.ownerDocument.createElement("Dummy")
|
dummy = newNode(node, "Dummy")
|
||||||
dummy.appendChild(node)
|
dummy.appendChild(node)
|
||||||
l.append(decode_item(dummy, errs, where + unicode("[%s]" % ix)))
|
l.append(decode_item(dummy, errs, where + unicode("[%s]" % ix)))
|
||||||
#l.append(decode_item(node, errs, where + unicode("[%s]" % ix)))
|
#l.append(decode_item(node, errs, where + unicode("[%s]" % ix)))
|
||||||
|
|||||||
+4
-1
@@ -15,5 +15,8 @@ try:
|
|||||||
zimbabwe # comment out to disable piks
|
zimbabwe # comment out to disable piks
|
||||||
from xmlextpiks import *
|
from xmlextpiks import *
|
||||||
except:
|
except:
|
||||||
print 'xmlext: piksemel implementation cannot be loaded, falling back to minidom'
|
try:
|
||||||
|
from xmlextcdom import *
|
||||||
|
except:
|
||||||
|
print 'xmlext: cDomlette/piksemel implementation cannot be loaded, falling back to minidom'
|
||||||
from xmlextmdom import *
|
from xmlextmdom import *
|
||||||
|
|||||||
@@ -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)
|
||||||
+5
-3
@@ -13,8 +13,10 @@
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
horagata # comment out to disable piks
|
horagata # comment out to disable piks
|
||||||
from xmlextpiks import *
|
#from xmlfilepiks import *
|
||||||
from xmlfilepiks import *
|
|
||||||
except:
|
except:
|
||||||
print 'xmlfile: piksemel implementation cannot be loaded, falling back to minidom'
|
try:
|
||||||
|
from xmlfilecdom import *
|
||||||
|
except:
|
||||||
|
print 'xmlext: cDomlette/piksemel implementation cannot be loaded, falling back to minidom'
|
||||||
from xmlfilemdom import *
|
from xmlfilemdom import *
|
||||||
|
|||||||
@@ -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))
|
||||||
@@ -43,9 +43,9 @@ class XmlFile(object):
|
|||||||
|
|
||||||
def __init__(self, tag):
|
def __init__(self, tag):
|
||||||
self.rootTag = tag
|
self.rootTag = tag
|
||||||
self.newDOM()
|
self.newDocument()
|
||||||
|
|
||||||
def newDOM(self):
|
def newDocument(self):
|
||||||
"""clear DOM"""
|
"""clear DOM"""
|
||||||
impl = mdom.getDOMImplementation()
|
impl = mdom.getDOMImplementation()
|
||||||
self.dom = impl.createDocument(None, self.rootTag, None)
|
self.dom = impl.createDocument(None, self.rootTag, None)
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ class XmlFile(object):
|
|||||||
|
|
||||||
def __init__(self, tag):
|
def __init__(self, tag):
|
||||||
self.rootTag = tag
|
self.rootTag = tag
|
||||||
self.newDOM()
|
self.newDocument()
|
||||||
|
|
||||||
def newDOM(self):
|
def newDocument(self):
|
||||||
"""clear DOM"""
|
"""clear DOM"""
|
||||||
self.doc = newDocument(self.rootTag)
|
self.doc = newDocument(self.rootTag)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user