From c4fe20dc326fccf524a25787301439fb0c1eeb37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eray=20=C3=96zkural?= Date: Wed, 9 Nov 2005 17:40:54 +0000 Subject: [PATCH] * support for multiple xml implementations * inform other modules that autoxml has been factored out --- pisi/autoxml.py | 3 +- pisi/dependency.py | 14 ++-- pisi/files.py | 18 ++--- pisi/index.py | 8 +-- pisi/metadata.py | 33 ++++----- pisi/specfile.py | 110 ++++++++++++++-------------- pisi/xmlext.py | 14 ++++ pisi/xmlextmdom.py | 9 ++- pisi/xmlextpiks.py | 170 ++++++++++++++++++++++++++++++++++++++++++++ pisi/xmlfilemdom.py | 154 +++++++++++++++++++++++++++++++++++++++ pisi/xmlfilepiks.py | 150 ++++++++++++++++++++++++++++++++++++++ 11 files changed, 590 insertions(+), 93 deletions(-) create mode 100644 pisi/xmlext.py create mode 100644 pisi/xmlextpiks.py create mode 100644 pisi/xmlfilemdom.py create mode 100644 pisi/xmlfilepiks.py diff --git a/pisi/autoxml.py b/pisi/autoxml.py index 5a5c2bb6..45ec0467 100644 --- a/pisi/autoxml.py +++ b/pisi/autoxml.py @@ -41,7 +41,8 @@ _ = __trans.ugettext # PiSi import pisi # TODO: find the appropriate xmlext implementation and import from there -from pisi.xmlextmdom import * +from pisi.xmlext import * +from pisi.xmlfile import XmlFile import pisi.context as ctx import pisi.util as util import pisi.oo as oo diff --git a/pisi/dependency.py b/pisi/dependency.py index fd2ec3a6..28ea779d 100644 --- a/pisi/dependency.py +++ b/pisi/dependency.py @@ -21,18 +21,18 @@ _ = __trans.ugettext import pisi.context as ctx import pisi.packagedb as packagedb from pisi.version import Version -import pisi.xmlfile as xmlfile +import pisi.autoxml as autoxml from pisi.util import Checks class Dependency: - __metaclass__ = xmlfile.autoxml + __metaclass__ = autoxml.autoxml - s_Package = [xmlfile.String, xmlfile.mandatory] - a_versionFrom = [xmlfile.String, xmlfile.optional] - a_versionTo = [xmlfile.String, xmlfile.optional] - a_releaseFrom = [xmlfile.String, xmlfile.optional] - a_releaseTo = [xmlfile.String, xmlfile.optional] + s_Package = [autoxml.String, autoxml.mandatory] + a_versionFrom = [autoxml.String, autoxml.optional] + a_versionTo = [autoxml.String, autoxml.optional] + a_releaseFrom = [autoxml.String, autoxml.optional] + a_releaseTo = [autoxml.String, autoxml.optional] def __str__(self): s = self.package diff --git a/pisi/files.py b/pisi/files.py index 2db0bb75..2dd7d837 100644 --- a/pisi/files.py +++ b/pisi/files.py @@ -15,32 +15,32 @@ # Authors: Eray Ozkural -import pisi.xmlfile as xmlfile +import pisi.autoxml as autoxml from pisi.util import Checks import pisi.lockeddbshelve as shelve class File: """File holds the information for a File node/tag in files.xml""" - __metaclass__ = xmlfile.autoxml + __metaclass__ = autoxml.autoxml - t_Path = [ xmlfile.String, xmlfile.mandatory ] - t_Type = [ xmlfile.String, xmlfile.mandatory ] - t_Size = [ xmlfile.Long, xmlfile.optional ] - t_Hash = [ xmlfile.String, xmlfile.optional, "SHA1Sum" ] + t_Path = [ autoxml.String, autoxml.mandatory ] + t_Type = [ autoxml.String, autoxml.mandatory ] + t_Size = [ autoxml.Long, autoxml.optional ] + t_Hash = [ autoxml.String, autoxml.optional, "SHA1Sum" ] def __str__(self): s = "%s, type: %s, size: %s, sha1sum: %s" % (self.path, self.type, self.size, self.hash) return s -class Files(xmlfile.XmlFile): +class Files(autoxml.XmlFile): - __metaclass__ = xmlfile.autoxml + __metaclass__ = autoxml.autoxml tag = "Files" - t_List = [ [File], xmlfile.optional, "File"] + t_List = [ [File], autoxml.optional, "File"] def append(self, fileinfo): self.list.append(fileinfo) diff --git a/pisi/index.py b/pisi/index.py index edfc3da7..e7d0dcb6 100644 --- a/pisi/index.py +++ b/pisi/index.py @@ -29,19 +29,19 @@ import pisi.packagedb as packagedb import pisi.util as util from pisi.package import Package from pisi.xmlfile import XmlFile -import pisi.xmlfile as xmlfile +import pisi.autoxml as autoxml from pisi.uri import URI class Error(pisi.Error): pass class Index(XmlFile): - __metaclass__ = xmlfile.autoxml + __metaclass__ = autoxml.autoxml tag = "PISI" - t_Sources = [ [specfile.Source], xmlfile.optional, "Source"] - t_Packages = [ [metadata.Package], xmlfile.optional, "Package"] + t_Sources = [ [specfile.Source], autoxml.optional, "Source"] + t_Packages = [ [metadata.Package], autoxml.optional, "Package"] def read_uri(self, filename, repo = None): """Read PSPEC file""" diff --git a/pisi/metadata.py b/pisi/metadata.py index 4ba474b2..c367afa2 100644 --- a/pisi/metadata.py +++ b/pisi/metadata.py @@ -26,24 +26,25 @@ _ = __trans.ugettext import pisi.context as ctx import pisi.specfile as specfile import pisi.xmlfile as xmlfile +import pisi.autoxml as autoxml import pisi.util as util class Source: - __metaclass__ = xmlfile.autoxml + __metaclass__ = autoxml.autoxml - t_Name = [xmlfile.String, xmlfile.mandatory] - t_Homepage = [xmlfile.String, xmlfile.optional] - t_Packager = [specfile.Packager, xmlfile.mandatory] + t_Name = [autoxml.String, autoxml.mandatory] + t_Homepage = [autoxml.String, autoxml.optional] + t_Packager = [specfile.Packager, autoxml.mandatory] class Package(specfile.Package): - __metaclass__ = xmlfile.autoxml + __metaclass__ = autoxml.autoxml - t_Build = [ xmlfile.Integer, xmlfile.optional] - t_Distribution = [ xmlfile.String, xmlfile.mandatory] - t_DistributionRelease = [ xmlfile.String, xmlfile.mandatory] - t_Architecture = [ xmlfile.String, xmlfile.mandatory] - t_InstalledSize = [ xmlfile.Long, xmlfile.mandatory] - t_PackageURI = [ xmlfile.String, xmlfile.optional] + t_Build = [ autoxml.Integer, autoxml.optional] + t_Distribution = [ autoxml.String, autoxml.mandatory] + t_DistributionRelease = [ autoxml.String, autoxml.mandatory] + t_Architecture = [ autoxml.String, autoxml.mandatory] + t_InstalledSize = [ autoxml.Long, autoxml.mandatory] + t_PackageURI = [ autoxml.String, autoxml.optional] def decode_hook(self, node, errs, where): self.version = self.history[0].version @@ -57,17 +58,17 @@ class Package(specfile.Package): (self.architecture, self.installedSize) return s -class MetaData(xmlfile.XmlFile): +class MetaData(autoxml.XmlFile): """Package metadata. Metadata is composed of Specfile and various other information. A metadata has two parts, Source and Package.""" - __metaclass__ = xmlfile.autoxml + __metaclass__ = autoxml.autoxml tag = "PISI" - t_Source = [ Source, xmlfile.mandatory] - t_Package = [ Package, xmlfile.mandatory] - #t_History = [ [Update], xmlfile.mandatory] + t_Source = [ Source, autoxml.mandatory] + t_Package = [ Package, autoxml.mandatory] + #t_History = [ [Update], autoxml.mandatory] def from_spec(self, src, pkg): self.source.name = src.name diff --git a/pisi/specfile.py b/pisi/specfile.py index 6db64912..9a796981 100644 --- a/pisi/specfile.py +++ b/pisi/specfile.py @@ -26,8 +26,8 @@ _ = __trans.ugettext from os.path import basename # pisi modules -import pisi.xmlfile as xmlfile from pisi.xmlfile import XmlFile +import pisi.autoxml as autoxml import pisi.context as ctx from pisi.dependency import Dependency import pisi.dependency @@ -37,12 +37,12 @@ import pisi.util as util class Error(pisi.Error): pass -__metaclass__ = xmlfile.autoxml +__metaclass__ = autoxml.autoxml class Packager: - t_Name = [xmlfile.Text, xmlfile.mandatory] - t_Email = [xmlfile.String, xmlfile.mandatory] + t_Name = [autoxml.Text, autoxml.mandatory] + t_Email = [autoxml.String, autoxml.mandatory] def __str__(self): s = "%s <%s>" % (self.name, self.email) @@ -51,9 +51,9 @@ class Packager: class AdditionalFile: - s_Filename = [xmlfile.String, xmlfile.mandatory] - a_target = [xmlfile.String, xmlfile.mandatory] - a_permission = [xmlfile.String, xmlfile.optional] + s_Filename = [autoxml.String, autoxml.mandatory] + a_target = [autoxml.String, autoxml.mandatory] + a_permission = [autoxml.String, autoxml.optional] def __str__(self): s = "%s -> %s " % (self.filename, self.target) @@ -64,10 +64,10 @@ class AdditionalFile: class Patch: - s_Filename = [xmlfile.String, xmlfile.mandatory] - a_compressionType = [xmlfile.String, xmlfile.optional] - a_level = [xmlfile.Integer, xmlfile.optional] - a_target = [xmlfile.String, xmlfile.optional] + s_Filename = [autoxml.String, autoxml.mandatory] + a_compressionType = [autoxml.String, autoxml.optional] + a_level = [autoxml.Integer, autoxml.optional] + a_target = [autoxml.String, autoxml.optional] #FIXME: what's the cleanest way to give a default value for reading level? #def decode_hook(self, node, errs, where): @@ -87,10 +87,10 @@ class Patch: class Update: - a_release = [xmlfile.String, xmlfile.mandatory] - t_Date = [xmlfile.String, xmlfile.mandatory] - t_Version = [xmlfile.String, xmlfile.mandatory] - t_Type = [xmlfile.String, xmlfile.optional] + a_release = [autoxml.String, autoxml.mandatory] + t_Date = [autoxml.String, autoxml.mandatory] + t_Version = [autoxml.String, autoxml.mandatory] + t_Type = [autoxml.String, autoxml.optional] def __str__(self): s = self.date @@ -103,8 +103,8 @@ class Update: class Path: - s_Path = [xmlfile.String, xmlfile.mandatory] - a_fileType = [xmlfile.String, xmlfile.optional] + s_Path = [autoxml.String, autoxml.mandatory] + a_fileType = [autoxml.String, autoxml.optional] def __str__(self): s = self.path @@ -114,8 +114,8 @@ class Path: class ComarProvide: - s_om = [xmlfile.String, xmlfile.mandatory] - a_script = [xmlfile.String, xmlfile.mandatory] + s_om = [autoxml.String, autoxml.mandatory] + a_script = [autoxml.String, autoxml.mandatory] def __str__(self): # FIXME: descriptive enough? @@ -126,9 +126,9 @@ class ComarProvide: class Archive: - s_uri = [ xmlfile.String, xmlfile.mandatory ] - a_type =[ xmlfile.String, xmlfile.mandatory ] - a_sha1sum =[ xmlfile.String, xmlfile.mandatory ] + s_uri = [ autoxml.String, autoxml.mandatory ] + a_type =[ autoxml.String, autoxml.mandatory ] + a_sha1sum =[ autoxml.String, autoxml.mandatory ] def decode_hook(self, node, errs, where): self.name = basename(self.uri) @@ -140,38 +140,38 @@ class Archive: class Source: - t_Name = [xmlfile.String, xmlfile.mandatory] - t_Homepage = [xmlfile.String, xmlfile.optional] - t_Packager = [Packager, xmlfile.mandatory] - t_Summary = [xmlfile.LocalText, xmlfile.mandatory] - t_Description = [xmlfile.LocalText, xmlfile.mandatory] - t_IsA = [ [xmlfile.String], xmlfile.mandatory] - t_PartOf = [xmlfile.String, xmlfile.mandatory] - t_Icon = [ xmlfile.String, xmlfile.optional] - t_License = [ [xmlfile.String], xmlfile.mandatory] - t_Archive = [Archive, xmlfile.mandatory ] - t_Patches = [ [Patch], xmlfile.optional] - t_BuildDependencies = [ [Dependency], xmlfile.optional] - t_Version = [ xmlfile.String, xmlfile.optional] - t_Release = [ xmlfile.String, xmlfile.optional] + t_Name = [autoxml.String, autoxml.mandatory] + t_Homepage = [autoxml.String, autoxml.optional] + t_Packager = [Packager, autoxml.mandatory] + t_Summary = [autoxml.LocalText, autoxml.mandatory] + t_Description = [autoxml.LocalText, autoxml.mandatory] + t_IsA = [ [autoxml.String], autoxml.mandatory] + t_PartOf = [autoxml.String, autoxml.mandatory] + t_Icon = [ autoxml.String, autoxml.optional] + t_License = [ [autoxml.String], autoxml.mandatory] + t_Archive = [Archive, autoxml.mandatory ] + t_Patches = [ [Patch], autoxml.optional] + t_BuildDependencies = [ [Dependency], autoxml.optional] + t_Version = [ autoxml.String, autoxml.optional] + t_Release = [ autoxml.String, autoxml.optional] class Package: - t_Name = [ xmlfile.String, xmlfile.mandatory ] - t_Summary = [ xmlfile.LocalText, xmlfile.optional ] - t_Description = [ xmlfile.LocalText, xmlfile.optional ] - t_IsA = [ [xmlfile.String], xmlfile.optional] - t_PartOf = [xmlfile.String, xmlfile.optional] - t_License = [ [xmlfile.String], xmlfile.optional] - t_Icon = [ xmlfile.String, xmlfile.optional] - t_RuntimeDependencies = [ [Dependency], xmlfile.optional] - t_Files = [ [Path], xmlfile.optional] - t_Conflicts = [ [xmlfile.String], xmlfile.optional, "Conflicts/Package"] - t_ProvidesComar = [ [ComarProvide], xmlfile.optional, "Provides/COMAR"] - #t_RequiresComar = [ [xmlfile.String], xmlfile.mandatory, "Requires/COMAR"] - t_AdditionalFiles = [ [AdditionalFile], xmlfile.optional] - t_History = [ [Update], xmlfile.optional] + t_Name = [ autoxml.String, autoxml.mandatory ] + t_Summary = [ autoxml.LocalText, autoxml.optional ] + t_Description = [ autoxml.LocalText, autoxml.optional ] + t_IsA = [ [autoxml.String], autoxml.optional] + t_PartOf = [autoxml.String, autoxml.optional] + t_License = [ [autoxml.String], autoxml.optional] + t_Icon = [ autoxml.String, autoxml.optional] + t_RuntimeDependencies = [ [Dependency], autoxml.optional] + t_Files = [ [Path], autoxml.optional] + t_Conflicts = [ [autoxml.String], autoxml.optional, "Conflicts/Package"] + t_ProvidesComar = [ [ComarProvide], autoxml.optional, "Provides/COMAR"] + #t_RequiresComar = [ [autoxml.String], autoxml.mandatory, "Requires/COMAR"] + t_AdditionalFiles = [ [AdditionalFile], autoxml.optional] + t_History = [ [Update], autoxml.optional] def pkg_dir(self): packageDir = self.name + '-' \ @@ -198,18 +198,18 @@ class Package: class SpecFile(XmlFile): - __metaclass__ = xmlfile.autoxml #needed when we specify a superclass + __metaclass__ = autoxml.autoxml #needed when we specify a superclass tag = "PISI" - t_Source = [ Source, xmlfile.mandatory] - t_Packages = [ [Package], xmlfile.mandatory, "Package"] - t_History = [ [Update], xmlfile.mandatory] + t_Source = [ Source, autoxml.mandatory] + t_Packages = [ [Package], autoxml.mandatory, "Package"] + t_History = [ [Update], autoxml.mandatory] #we're not doing this with the init hook right now #def init(self, tag = "PISI"): #ignore tag - #XmlFile.__init__(self, tag) + #autoxml.__init__(self, tag) def read_hook(self, errs): """Read PSPEC file""" diff --git a/pisi/xmlext.py b/pisi/xmlext.py new file mode 100644 index 00000000..e21dffa4 --- /dev/null +++ b/pisi/xmlext.py @@ -0,0 +1,14 @@ +# -*- 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 + +from xmlextmdom import * diff --git a/pisi/xmlextmdom.py b/pisi/xmlextmdom.py index 66f2846a..e82e12ba 100644 --- a/pisi/xmlextmdom.py +++ b/pisi/xmlextmdom.py @@ -14,9 +14,16 @@ # Gurer Ozen """ - some helper functions implemented with minidom + xmlext is a helper module for accessing XML files using + xml.dom.minidom. + + 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' + note: this is a particularly inefficient implementation of xmlext. """ diff --git a/pisi/xmlextpiks.py b/pisi/xmlextpiks.py new file mode 100644 index 00000000..b4cdb926 --- /dev/null +++ b/pisi/xmlextpiks.py @@ -0,0 +1,170 @@ +# -*- 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 +# Baris Metin + +""" + some helper functions for high-level access to XML structures + + this implementation uses piksemel, a fast C-based XML library + + function names are mixedCase for compatibility with minidom, + an old library +""" + +import gettext +__trans = gettext.translation('pisi', fallback=True) +_ = __trans.ugettext + +import pisi +import piksemel as iks + +class XmlError(pisi.Error): + "named this way because the class if mostly used with an import *" + pass + +def getNodeAttribute(node, attrname): + """get named attribute from DOM node""" + if not node.hasAttribute(attrname): + return None + return node.getAttribute(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: + for child in node.childNodes: + if child.nodeType == node.ELEMENT_NODE and child.tagName == tag: + return child + return None + +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.createElement(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 newNode(node, tag): + return node.ownerDocument.createElement(tag) + +def newTextNode(node, text): + return node.ownerDocument.createTextNode(text) + +def addText(node, tagPath, text, branch = True): + newnode = newTextNode(node, text) + addNode(node, tagPath, newnode, branch) diff --git a/pisi/xmlfilemdom.py b/pisi/xmlfilemdom.py new file mode 100644 index 00000000..a8f44593 --- /dev/null +++ b/pisi/xmlfilemdom.py @@ -0,0 +1,154 @@ +# -*- 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 +# Baris Metin + +""" + 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' + + note: this is a particularly inefficient implementation of xmlfile +""" + +import gettext +__trans = gettext.translation('pisi', fallback=True) +_ = __trans.ugettext + +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.newDOM() + + def newDOM(self): + """clear DOM""" + impl = mdom.getDOMImplementation() + self.dom = impl.createDocument(None, self.rootTag, None) + + def unlink(self): + """deallocate DOM structure""" + self.dom.unlink() + + def rootNode(self): + """returns root document element""" + return self.dom.documentElement + + def readxml(self, fileName): + try: + self.dom = mdom.parse(fileName) + except ExpatError, inst: + raise XmlError(_("File '%s' has invalid XML: %s\n") % (fileName, + str(inst))) + + def writexml(self, fileName): + f = codecs.open(fileName,'w', "utf-8") + f.write(self.dom.toprettyxml()) + 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.createElement(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)) diff --git a/pisi/xmlfilepiks.py b/pisi/xmlfilepiks.py new file mode 100644 index 00000000..71e3ffd6 --- /dev/null +++ b/pisi/xmlfilepiks.py @@ -0,0 +1,150 @@ +# -*- 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 +# Gurer Ozen +# Baris Metin