* support for multiple xml implementations
* inform other modules that autoxml has been factored out
This commit is contained in:
+2
-1
@@ -41,7 +41,8 @@ _ = __trans.ugettext
|
|||||||
# PiSi
|
# PiSi
|
||||||
import pisi
|
import pisi
|
||||||
# TODO: find the appropriate xmlext implementation and import from there
|
# 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.context as ctx
|
||||||
import pisi.util as util
|
import pisi.util as util
|
||||||
import pisi.oo as oo
|
import pisi.oo as oo
|
||||||
|
|||||||
+7
-7
@@ -21,18 +21,18 @@ _ = __trans.ugettext
|
|||||||
import pisi.context as ctx
|
import pisi.context as ctx
|
||||||
import pisi.packagedb as packagedb
|
import pisi.packagedb as packagedb
|
||||||
from pisi.version import Version
|
from pisi.version import Version
|
||||||
import pisi.xmlfile as xmlfile
|
import pisi.autoxml as autoxml
|
||||||
from pisi.util import Checks
|
from pisi.util import Checks
|
||||||
|
|
||||||
class Dependency:
|
class Dependency:
|
||||||
|
|
||||||
__metaclass__ = xmlfile.autoxml
|
__metaclass__ = autoxml.autoxml
|
||||||
|
|
||||||
s_Package = [xmlfile.String, xmlfile.mandatory]
|
s_Package = [autoxml.String, autoxml.mandatory]
|
||||||
a_versionFrom = [xmlfile.String, xmlfile.optional]
|
a_versionFrom = [autoxml.String, autoxml.optional]
|
||||||
a_versionTo = [xmlfile.String, xmlfile.optional]
|
a_versionTo = [autoxml.String, autoxml.optional]
|
||||||
a_releaseFrom = [xmlfile.String, xmlfile.optional]
|
a_releaseFrom = [autoxml.String, autoxml.optional]
|
||||||
a_releaseTo = [xmlfile.String, xmlfile.optional]
|
a_releaseTo = [autoxml.String, autoxml.optional]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = self.package
|
s = self.package
|
||||||
|
|||||||
+9
-9
@@ -15,32 +15,32 @@
|
|||||||
|
|
||||||
# Authors: Eray Ozkural <eray@uludag.org.tr>
|
# Authors: Eray Ozkural <eray@uludag.org.tr>
|
||||||
|
|
||||||
import pisi.xmlfile as xmlfile
|
import pisi.autoxml as autoxml
|
||||||
from pisi.util import Checks
|
from pisi.util import Checks
|
||||||
import pisi.lockeddbshelve as shelve
|
import pisi.lockeddbshelve as shelve
|
||||||
|
|
||||||
class File:
|
class File:
|
||||||
"""File holds the information for a File node/tag in files.xml"""
|
"""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_Path = [ autoxml.String, autoxml.mandatory ]
|
||||||
t_Type = [ xmlfile.String, xmlfile.mandatory ]
|
t_Type = [ autoxml.String, autoxml.mandatory ]
|
||||||
t_Size = [ xmlfile.Long, xmlfile.optional ]
|
t_Size = [ autoxml.Long, autoxml.optional ]
|
||||||
t_Hash = [ xmlfile.String, xmlfile.optional, "SHA1Sum" ]
|
t_Hash = [ autoxml.String, autoxml.optional, "SHA1Sum" ]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = "%s, type: %s, size: %s, sha1sum: %s" % (self.path, self.type,
|
s = "%s, type: %s, size: %s, sha1sum: %s" % (self.path, self.type,
|
||||||
self.size, self.hash)
|
self.size, self.hash)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
class Files(xmlfile.XmlFile):
|
class Files(autoxml.XmlFile):
|
||||||
|
|
||||||
__metaclass__ = xmlfile.autoxml
|
__metaclass__ = autoxml.autoxml
|
||||||
|
|
||||||
tag = "Files"
|
tag = "Files"
|
||||||
|
|
||||||
t_List = [ [File], xmlfile.optional, "File"]
|
t_List = [ [File], autoxml.optional, "File"]
|
||||||
|
|
||||||
def append(self, fileinfo):
|
def append(self, fileinfo):
|
||||||
self.list.append(fileinfo)
|
self.list.append(fileinfo)
|
||||||
|
|||||||
+4
-4
@@ -29,19 +29,19 @@ import pisi.packagedb as packagedb
|
|||||||
import pisi.util as util
|
import pisi.util as util
|
||||||
from pisi.package import Package
|
from pisi.package import Package
|
||||||
from pisi.xmlfile import XmlFile
|
from pisi.xmlfile import XmlFile
|
||||||
import pisi.xmlfile as xmlfile
|
import pisi.autoxml as autoxml
|
||||||
from pisi.uri import URI
|
from pisi.uri import URI
|
||||||
|
|
||||||
class Error(pisi.Error):
|
class Error(pisi.Error):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
class Index(XmlFile):
|
class Index(XmlFile):
|
||||||
__metaclass__ = xmlfile.autoxml
|
__metaclass__ = autoxml.autoxml
|
||||||
|
|
||||||
tag = "PISI"
|
tag = "PISI"
|
||||||
|
|
||||||
t_Sources = [ [specfile.Source], xmlfile.optional, "Source"]
|
t_Sources = [ [specfile.Source], autoxml.optional, "Source"]
|
||||||
t_Packages = [ [metadata.Package], xmlfile.optional, "Package"]
|
t_Packages = [ [metadata.Package], autoxml.optional, "Package"]
|
||||||
|
|
||||||
def read_uri(self, filename, repo = None):
|
def read_uri(self, filename, repo = None):
|
||||||
"""Read PSPEC file"""
|
"""Read PSPEC file"""
|
||||||
|
|||||||
+17
-16
@@ -26,24 +26,25 @@ _ = __trans.ugettext
|
|||||||
import pisi.context as ctx
|
import pisi.context as ctx
|
||||||
import pisi.specfile as specfile
|
import pisi.specfile as specfile
|
||||||
import pisi.xmlfile as xmlfile
|
import pisi.xmlfile as xmlfile
|
||||||
|
import pisi.autoxml as autoxml
|
||||||
import pisi.util as util
|
import pisi.util as util
|
||||||
|
|
||||||
class Source:
|
class Source:
|
||||||
__metaclass__ = xmlfile.autoxml
|
__metaclass__ = autoxml.autoxml
|
||||||
|
|
||||||
t_Name = [xmlfile.String, xmlfile.mandatory]
|
t_Name = [autoxml.String, autoxml.mandatory]
|
||||||
t_Homepage = [xmlfile.String, xmlfile.optional]
|
t_Homepage = [autoxml.String, autoxml.optional]
|
||||||
t_Packager = [specfile.Packager, xmlfile.mandatory]
|
t_Packager = [specfile.Packager, autoxml.mandatory]
|
||||||
|
|
||||||
class Package(specfile.Package):
|
class Package(specfile.Package):
|
||||||
__metaclass__ = xmlfile.autoxml
|
__metaclass__ = autoxml.autoxml
|
||||||
|
|
||||||
t_Build = [ xmlfile.Integer, xmlfile.optional]
|
t_Build = [ autoxml.Integer, autoxml.optional]
|
||||||
t_Distribution = [ xmlfile.String, xmlfile.mandatory]
|
t_Distribution = [ autoxml.String, autoxml.mandatory]
|
||||||
t_DistributionRelease = [ xmlfile.String, xmlfile.mandatory]
|
t_DistributionRelease = [ autoxml.String, autoxml.mandatory]
|
||||||
t_Architecture = [ xmlfile.String, xmlfile.mandatory]
|
t_Architecture = [ autoxml.String, autoxml.mandatory]
|
||||||
t_InstalledSize = [ xmlfile.Long, xmlfile.mandatory]
|
t_InstalledSize = [ autoxml.Long, autoxml.mandatory]
|
||||||
t_PackageURI = [ xmlfile.String, xmlfile.optional]
|
t_PackageURI = [ autoxml.String, autoxml.optional]
|
||||||
|
|
||||||
def decode_hook(self, node, errs, where):
|
def decode_hook(self, node, errs, where):
|
||||||
self.version = self.history[0].version
|
self.version = self.history[0].version
|
||||||
@@ -57,17 +58,17 @@ class Package(specfile.Package):
|
|||||||
(self.architecture, self.installedSize)
|
(self.architecture, self.installedSize)
|
||||||
return s
|
return s
|
||||||
|
|
||||||
class MetaData(xmlfile.XmlFile):
|
class MetaData(autoxml.XmlFile):
|
||||||
"""Package metadata. Metadata is composed of Specfile and various
|
"""Package metadata. Metadata is composed of Specfile and various
|
||||||
other information. A metadata has two parts, Source and Package."""
|
other information. A metadata has two parts, Source and Package."""
|
||||||
|
|
||||||
__metaclass__ = xmlfile.autoxml
|
__metaclass__ = autoxml.autoxml
|
||||||
|
|
||||||
tag = "PISI"
|
tag = "PISI"
|
||||||
|
|
||||||
t_Source = [ Source, xmlfile.mandatory]
|
t_Source = [ Source, autoxml.mandatory]
|
||||||
t_Package = [ Package, xmlfile.mandatory]
|
t_Package = [ Package, autoxml.mandatory]
|
||||||
#t_History = [ [Update], xmlfile.mandatory]
|
#t_History = [ [Update], autoxml.mandatory]
|
||||||
|
|
||||||
def from_spec(self, src, pkg):
|
def from_spec(self, src, pkg):
|
||||||
self.source.name = src.name
|
self.source.name = src.name
|
||||||
|
|||||||
+55
-55
@@ -26,8 +26,8 @@ _ = __trans.ugettext
|
|||||||
from os.path import basename
|
from os.path import basename
|
||||||
|
|
||||||
# pisi modules
|
# pisi modules
|
||||||
import pisi.xmlfile as xmlfile
|
|
||||||
from pisi.xmlfile import XmlFile
|
from pisi.xmlfile import XmlFile
|
||||||
|
import pisi.autoxml as autoxml
|
||||||
import pisi.context as ctx
|
import pisi.context as ctx
|
||||||
from pisi.dependency import Dependency
|
from pisi.dependency import Dependency
|
||||||
import pisi.dependency
|
import pisi.dependency
|
||||||
@@ -37,12 +37,12 @@ import pisi.util as util
|
|||||||
class Error(pisi.Error):
|
class Error(pisi.Error):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
__metaclass__ = xmlfile.autoxml
|
__metaclass__ = autoxml.autoxml
|
||||||
|
|
||||||
class Packager:
|
class Packager:
|
||||||
|
|
||||||
t_Name = [xmlfile.Text, xmlfile.mandatory]
|
t_Name = [autoxml.Text, autoxml.mandatory]
|
||||||
t_Email = [xmlfile.String, xmlfile.mandatory]
|
t_Email = [autoxml.String, autoxml.mandatory]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = "%s <%s>" % (self.name, self.email)
|
s = "%s <%s>" % (self.name, self.email)
|
||||||
@@ -51,9 +51,9 @@ class Packager:
|
|||||||
|
|
||||||
class AdditionalFile:
|
class AdditionalFile:
|
||||||
|
|
||||||
s_Filename = [xmlfile.String, xmlfile.mandatory]
|
s_Filename = [autoxml.String, autoxml.mandatory]
|
||||||
a_target = [xmlfile.String, xmlfile.mandatory]
|
a_target = [autoxml.String, autoxml.mandatory]
|
||||||
a_permission = [xmlfile.String, xmlfile.optional]
|
a_permission = [autoxml.String, autoxml.optional]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = "%s -> %s " % (self.filename, self.target)
|
s = "%s -> %s " % (self.filename, self.target)
|
||||||
@@ -64,10 +64,10 @@ class AdditionalFile:
|
|||||||
|
|
||||||
class Patch:
|
class Patch:
|
||||||
|
|
||||||
s_Filename = [xmlfile.String, xmlfile.mandatory]
|
s_Filename = [autoxml.String, autoxml.mandatory]
|
||||||
a_compressionType = [xmlfile.String, xmlfile.optional]
|
a_compressionType = [autoxml.String, autoxml.optional]
|
||||||
a_level = [xmlfile.Integer, xmlfile.optional]
|
a_level = [autoxml.Integer, autoxml.optional]
|
||||||
a_target = [xmlfile.String, xmlfile.optional]
|
a_target = [autoxml.String, autoxml.optional]
|
||||||
|
|
||||||
#FIXME: what's the cleanest way to give a default value for reading level?
|
#FIXME: what's the cleanest way to give a default value for reading level?
|
||||||
#def decode_hook(self, node, errs, where):
|
#def decode_hook(self, node, errs, where):
|
||||||
@@ -87,10 +87,10 @@ class Patch:
|
|||||||
|
|
||||||
class Update:
|
class Update:
|
||||||
|
|
||||||
a_release = [xmlfile.String, xmlfile.mandatory]
|
a_release = [autoxml.String, autoxml.mandatory]
|
||||||
t_Date = [xmlfile.String, xmlfile.mandatory]
|
t_Date = [autoxml.String, autoxml.mandatory]
|
||||||
t_Version = [xmlfile.String, xmlfile.mandatory]
|
t_Version = [autoxml.String, autoxml.mandatory]
|
||||||
t_Type = [xmlfile.String, xmlfile.optional]
|
t_Type = [autoxml.String, autoxml.optional]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = self.date
|
s = self.date
|
||||||
@@ -103,8 +103,8 @@ class Update:
|
|||||||
|
|
||||||
class Path:
|
class Path:
|
||||||
|
|
||||||
s_Path = [xmlfile.String, xmlfile.mandatory]
|
s_Path = [autoxml.String, autoxml.mandatory]
|
||||||
a_fileType = [xmlfile.String, xmlfile.optional]
|
a_fileType = [autoxml.String, autoxml.optional]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
s = self.path
|
s = self.path
|
||||||
@@ -114,8 +114,8 @@ class Path:
|
|||||||
|
|
||||||
class ComarProvide:
|
class ComarProvide:
|
||||||
|
|
||||||
s_om = [xmlfile.String, xmlfile.mandatory]
|
s_om = [autoxml.String, autoxml.mandatory]
|
||||||
a_script = [xmlfile.String, xmlfile.mandatory]
|
a_script = [autoxml.String, autoxml.mandatory]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# FIXME: descriptive enough?
|
# FIXME: descriptive enough?
|
||||||
@@ -126,9 +126,9 @@ class ComarProvide:
|
|||||||
|
|
||||||
class Archive:
|
class Archive:
|
||||||
|
|
||||||
s_uri = [ xmlfile.String, xmlfile.mandatory ]
|
s_uri = [ autoxml.String, autoxml.mandatory ]
|
||||||
a_type =[ xmlfile.String, xmlfile.mandatory ]
|
a_type =[ autoxml.String, autoxml.mandatory ]
|
||||||
a_sha1sum =[ xmlfile.String, xmlfile.mandatory ]
|
a_sha1sum =[ autoxml.String, autoxml.mandatory ]
|
||||||
|
|
||||||
def decode_hook(self, node, errs, where):
|
def decode_hook(self, node, errs, where):
|
||||||
self.name = basename(self.uri)
|
self.name = basename(self.uri)
|
||||||
@@ -140,38 +140,38 @@ class Archive:
|
|||||||
|
|
||||||
class Source:
|
class Source:
|
||||||
|
|
||||||
t_Name = [xmlfile.String, xmlfile.mandatory]
|
t_Name = [autoxml.String, autoxml.mandatory]
|
||||||
t_Homepage = [xmlfile.String, xmlfile.optional]
|
t_Homepage = [autoxml.String, autoxml.optional]
|
||||||
t_Packager = [Packager, xmlfile.mandatory]
|
t_Packager = [Packager, autoxml.mandatory]
|
||||||
t_Summary = [xmlfile.LocalText, xmlfile.mandatory]
|
t_Summary = [autoxml.LocalText, autoxml.mandatory]
|
||||||
t_Description = [xmlfile.LocalText, xmlfile.mandatory]
|
t_Description = [autoxml.LocalText, autoxml.mandatory]
|
||||||
t_IsA = [ [xmlfile.String], xmlfile.mandatory]
|
t_IsA = [ [autoxml.String], autoxml.mandatory]
|
||||||
t_PartOf = [xmlfile.String, xmlfile.mandatory]
|
t_PartOf = [autoxml.String, autoxml.mandatory]
|
||||||
t_Icon = [ xmlfile.String, xmlfile.optional]
|
t_Icon = [ autoxml.String, autoxml.optional]
|
||||||
t_License = [ [xmlfile.String], xmlfile.mandatory]
|
t_License = [ [autoxml.String], autoxml.mandatory]
|
||||||
t_Archive = [Archive, xmlfile.mandatory ]
|
t_Archive = [Archive, autoxml.mandatory ]
|
||||||
t_Patches = [ [Patch], xmlfile.optional]
|
t_Patches = [ [Patch], autoxml.optional]
|
||||||
t_BuildDependencies = [ [Dependency], xmlfile.optional]
|
t_BuildDependencies = [ [Dependency], autoxml.optional]
|
||||||
t_Version = [ xmlfile.String, xmlfile.optional]
|
t_Version = [ autoxml.String, autoxml.optional]
|
||||||
t_Release = [ xmlfile.String, xmlfile.optional]
|
t_Release = [ autoxml.String, autoxml.optional]
|
||||||
|
|
||||||
|
|
||||||
class Package:
|
class Package:
|
||||||
|
|
||||||
t_Name = [ xmlfile.String, xmlfile.mandatory ]
|
t_Name = [ autoxml.String, autoxml.mandatory ]
|
||||||
t_Summary = [ xmlfile.LocalText, xmlfile.optional ]
|
t_Summary = [ autoxml.LocalText, autoxml.optional ]
|
||||||
t_Description = [ xmlfile.LocalText, xmlfile.optional ]
|
t_Description = [ autoxml.LocalText, autoxml.optional ]
|
||||||
t_IsA = [ [xmlfile.String], xmlfile.optional]
|
t_IsA = [ [autoxml.String], autoxml.optional]
|
||||||
t_PartOf = [xmlfile.String, xmlfile.optional]
|
t_PartOf = [autoxml.String, autoxml.optional]
|
||||||
t_License = [ [xmlfile.String], xmlfile.optional]
|
t_License = [ [autoxml.String], autoxml.optional]
|
||||||
t_Icon = [ xmlfile.String, xmlfile.optional]
|
t_Icon = [ autoxml.String, autoxml.optional]
|
||||||
t_RuntimeDependencies = [ [Dependency], xmlfile.optional]
|
t_RuntimeDependencies = [ [Dependency], autoxml.optional]
|
||||||
t_Files = [ [Path], xmlfile.optional]
|
t_Files = [ [Path], autoxml.optional]
|
||||||
t_Conflicts = [ [xmlfile.String], xmlfile.optional, "Conflicts/Package"]
|
t_Conflicts = [ [autoxml.String], autoxml.optional, "Conflicts/Package"]
|
||||||
t_ProvidesComar = [ [ComarProvide], xmlfile.optional, "Provides/COMAR"]
|
t_ProvidesComar = [ [ComarProvide], autoxml.optional, "Provides/COMAR"]
|
||||||
#t_RequiresComar = [ [xmlfile.String], xmlfile.mandatory, "Requires/COMAR"]
|
#t_RequiresComar = [ [autoxml.String], autoxml.mandatory, "Requires/COMAR"]
|
||||||
t_AdditionalFiles = [ [AdditionalFile], xmlfile.optional]
|
t_AdditionalFiles = [ [AdditionalFile], autoxml.optional]
|
||||||
t_History = [ [Update], xmlfile.optional]
|
t_History = [ [Update], autoxml.optional]
|
||||||
|
|
||||||
def pkg_dir(self):
|
def pkg_dir(self):
|
||||||
packageDir = self.name + '-' \
|
packageDir = self.name + '-' \
|
||||||
@@ -198,18 +198,18 @@ class Package:
|
|||||||
|
|
||||||
|
|
||||||
class SpecFile(XmlFile):
|
class SpecFile(XmlFile):
|
||||||
__metaclass__ = xmlfile.autoxml #needed when we specify a superclass
|
__metaclass__ = autoxml.autoxml #needed when we specify a superclass
|
||||||
|
|
||||||
tag = "PISI"
|
tag = "PISI"
|
||||||
|
|
||||||
t_Source = [ Source, xmlfile.mandatory]
|
t_Source = [ Source, autoxml.mandatory]
|
||||||
t_Packages = [ [Package], xmlfile.mandatory, "Package"]
|
t_Packages = [ [Package], autoxml.mandatory, "Package"]
|
||||||
t_History = [ [Update], xmlfile.mandatory]
|
t_History = [ [Update], autoxml.mandatory]
|
||||||
|
|
||||||
#we're not doing this with the init hook right now
|
#we're not doing this with the init hook right now
|
||||||
#def init(self, tag = "PISI"):
|
#def init(self, tag = "PISI"):
|
||||||
#ignore tag
|
#ignore tag
|
||||||
#XmlFile.__init__(self, tag)
|
#autoxml.__init__(self, tag)
|
||||||
|
|
||||||
def read_hook(self, errs):
|
def read_hook(self, errs):
|
||||||
"""Read PSPEC file"""
|
"""Read PSPEC file"""
|
||||||
|
|||||||
@@ -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 <eray@uludag.org.tr>
|
||||||
|
|
||||||
|
from xmlextmdom import *
|
||||||
+8
-1
@@ -14,9 +14,16 @@
|
|||||||
# Gurer Ozen <gurer@uludag.org.tr>
|
# Gurer Ozen <gurer@uludag.org.tr>
|
||||||
|
|
||||||
"""
|
"""
|
||||||
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,
|
function names are mixedCase for compatibility with minidom,
|
||||||
an 'old library'
|
an 'old library'
|
||||||
|
|
||||||
note: this is a particularly inefficient implementation of xmlext.
|
note: this is a particularly inefficient implementation of xmlext.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|||||||
@@ -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 <eray@uludag.org.tr>
|
||||||
|
# Baris Metin <baris@uludag.org.tr
|
||||||
|
# Gurer Ozen <gurer@uludag.org.tr>
|
||||||
|
|
||||||
|
"""
|
||||||
|
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)
|
||||||
@@ -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 <eray@uludag.org.tr>
|
||||||
|
# Baris Metin <baris@uludag.org.tr
|
||||||
|
# Gurer Ozen <gurer@uludag.org.tr>
|
||||||
|
|
||||||
|
"""
|
||||||
|
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))
|
||||||
@@ -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 <eray@uludag.org.tr>
|
||||||
|
# Gurer Ozen <gurer@uludag.org.tr>
|
||||||
|
# Baris Metin <baris@uludag.org.tr
|
||||||
|
|
||||||
|
"""
|
||||||
|
XmlFile class further abstracts a dom object using the
|
||||||
|
high-level dom functions provided in xmlext module
|
||||||
|
|
||||||
|
this implementation uses piksemel, a fast C-based XML library
|
||||||
|
"""
|
||||||
|
|
||||||
|
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))
|
||||||
Reference in New Issue
Block a user