Source code for objconfig.reader.xml
r"""
This is a port of zend-config to Python
Some idioms of PHP are still employed, but where possible I have Pythonized it
IGNORE:
Author: Asher Wolfstein Copyright 2017
Blog: http://wunk.me/
E-Mail: asherwunk@gmail.com
Twitter: https://twitter.com/asherwolfstein Send Me Some Love!
Package Homepage: http://wunk.me/programming-projects/objconfig-python/
GitHub: http://github.com/asherwunk/objconfig for the source repository
DevPost: https://devpost.com/software/objconfig
Buy Me A Coffee: https://ko-fi.com/A18224XC
Support Me On Patreon: https://www.patreon.com/asherwolfstein
IGNORE
Following is the header as given in zend-config::
/**
* Zend Framework (http://framework.zend.com/)
*
* @link http://github.com/zendframework/zf2 for the
* canonical source repository
* @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc.
* (http://www.zend.com)
* @license http://framework.zend.com/license/new-bsd New BSD License
*/
"""
from objconfig.reader import ReaderInterface
from objconfig.exception import RuntimeException
import xml.etree.ElementTree as ElementTree
import xml.etree.ElementInclude as ElementInclude
import os
[docs]class Xml(ReaderInterface):
r"""
Following is the class documentation as given in zend-config::
/**
* XML config reader.
*/
"""
[docs] def loader(self, href, parse, encoding=None):
"""
Load the XML file from a file location
Args:
href: absolute/relative location of the file
parse: do we immediately parse the file
encoding: useful if not parsing, decodes the file from this encoding
Returns:
The file decoded file data if not parsed, otherwise the the ElementTree.parsed() root
"""
if href[0] != '/':
href = os.path.join(self.directory, href)
if not os.path.isfile(href) or not os.access(href, os.R_OK):
raise RuntimeException("Xml: File %s Doesn't Exist or Not Readable (xi)" % href)
file = open(href)
if parse == "xml":
data = ElementTree.parse(file).getroot()
else:
data = file.read()
if encoding:
data = data.decode(encoding)
file.close()
return data
def __init__(self):
"""Initialize root and directory."""
r"""
Actually ElementTree root element
Following is the header as given in zend-config::
/**
* XML Reader instance.
*
* @var XMLReader
*/
"""
self.root = None
r"""
Following is the header as given in zend-config::
/**
* Directory of the JSON file
*
* @var string
*/
"""
self.directory = ''
[docs] def fromFile(self, filename):
r"""
Following is the header as given in zend-config::
/**
* fromFile(): defined by Reader interface.
*
* @see ReaderInterface::fromFile()
* @param string $filename
* @return array
* @throws Exception\RuntimeException
*/
"""
if not os.path.isfile(filename) and not os.access(filename, os.R_OK):
raise RuntimeException("Xml: File %s Doesn't Exist or Not Readable" % filename)
self.directory = os.path.dirname(filename.rstrip(os.sep)) or '.'
try:
xmlcontent = ''
with open(filename, "r") as file:
for line in file:
if "@include" in line:
include = line.split(":")[1].strip()
with open(os.path.join(self.directory, include), "r") as includedfile:
for includedline in includedfile:
xmlcontent += includedline
else:
xmlcontent += line
self.root = ElementTree.fromstring(xmlcontent)
ElementInclude.include(self.root, self.loader)
except ElementTree.ParseError as e:
raise RuntimeException("Xml: Error Reading XML file \"%s\": %s" % (filename, e))
return self.process(self.root)
[docs] def fromString(self, string):
r"""
Following is the header as given in zend-config::
/**
* fromString(): defined by Reader interface.
*
* @param string $string
* @return array|bool
* @throws Exception\RuntimeException
*/
"""
if not string:
return {}
self.directory = None
if "@include" in string:
raise RuntimeException("Xml: Cannot Process @include When Reading From String")
try:
self.root = ElementTree.fromstring(string)
except ElementTree.ParseError as e:
raise RuntimeException("Xml: Error Reading XML string: %s" % e)
return self.process(self.root)
[docs] def process(self, elem):
r"""
Following is the header as given in zend-config::
/**
* Process the next inner element.
*
* @return mixed
*/
"""
ret = {}
for child in elem:
if not child.getchildren():
if child.attrib and ("value" in child.attrib):
ret[child.tag] = child.attrib["value"]
else:
ret[child.tag] = child.text
else:
ret[child.tag] = self.process(child)
return ret