On 01/09/2014 06:32 PM, lvroyce(a)linux.vnet.ibm.com wrote:
From: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
Add an xml parser to xmlutils.py to deal with the increasing need
in kimchi to converse an xml to dict.
I have suggested to adopt this patch several
times. I need xml2dic.
But seems this patch is not welcome.
So Adam filed a issue about "generate and manipulate XML documents" 4
months ago.
https://github.com/kimchi-project/kimchi/issues/124
Also we has give up libvirt-gobject.
and now we can get a python third module on some distros.
on rhel6.5 and my F20
$ sudo yum search python-xmltodict
python-xmltodict.noarch : Makes working with XML feel like you are
working with JSON
we need xml2dict and dict2xml.
discuss with Mark about "generate and manipulate XML documents".
we think maybe lxml is good for us.
$ sudo yum search python-lxml
python-lxml-docs.noarch : Documentation for python-lxml
python-lxml.x86_64 : ElementTree-like Python bindings for libxml2 and
libxslt
you can consider lxml.
Signed-off-by: Bing Bu Cao <mars(a)linux.vnet.ibm.com>
Signed-off-by: Royce Lv <lvroyce(a)linux.vnet.ibm.com>
---
src/kimchi/exception.py | 4 ++++
src/kimchi/xmlutils.py | 54 ++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 55 insertions(+), 3 deletions(-)
diff --git a/src/kimchi/exception.py b/src/kimchi/exception.py
index bff0a18..623e6b3 100644
--- a/src/kimchi/exception.py
+++ b/src/kimchi/exception.py
@@ -43,3 +43,7 @@ class InvalidOperation(Exception):
class IsoFormatError(Exception):
pass
+
+
+class ParseError(Exception):
+ pass
diff --git a/src/kimchi/xmlutils.py b/src/kimchi/xmlutils.py
index 51ff0ec..f94db30 100644
--- a/src/kimchi/xmlutils.py
+++ b/src/kimchi/xmlutils.py
@@ -23,7 +23,11 @@
import libxml2
-from xml.etree import ElementTree
+from collections import defaultdict
+from xml.etree import ElementTree as ET
+
+
+from kimchi.exception import ParseError
def xpath_get_text(xml, expr):
@@ -36,7 +40,51 @@ def xpath_get_text(xml, expr):
def xml_item_update(xml, xpath, value):
- root = ElementTree.fromstring(xml)
+ root = ET.fromstring(xml)
item = root.find(xpath)
item.text = value
- return ElementTree.tostring(root, encoding="utf-8")
+ return ET.tostring(root, encoding="utf-8")
+
+
+def xml_to_dict(xml, fromstring=True):
+ try:
+ if fromstring:
+ t = ET.fromstring(xml)
+ else:
+ t = ET.parse(xml).getroot()
+ except ET.ParseError:
+ raise ParseError("XML parse failed, invalid XML file")
+ return _etree_to_dict(t)
+
+
+def _etree_to_dict(t):
+ # Convert an etree object to dict
+ d = {t.tag: {} if t.attrib else None}
+ children = list(t)
+ td = {}
+ if children:
+ dd = defaultdict(list)
+ #if has subelement, iteration as it's a new element
+ for dc in map(_etree_to_dict, children):
+ for k, v in dc.iteritems():
+ dd[k].append(v)
+ for k, v in dd.iteritems():
+ if len(v) == 1:
+ va = v[0]
+ else:
+ va = v
+ td.update({k: va})
+ d[t.tag] = td
+
+ #prepend '@' to attr and '#' to value
+ if t.attrib:
+ d[t.tag].update((k, v) for k, v in t.attrib.iteritems())
+ if t.text:
+ text = t.text.strip()
+ if children or t.attrib:
+ if text:
+ d[t.tag]['#value'] = text
+ else:
+ d[t.tag] = text
+
+ return d
--
Thanks and best regards!
Sheldon Feng(冯少合)<shaohef(a)linux.vnet.ibm.com>
IBM Linux Technology Center