Updated CVIssueCount to V3.1
This commit is contained in:
121
CVIssueCount/v3.1/xml2py.py
Normal file
121
CVIssueCount/v3.1/xml2py.py
Normal file
@@ -0,0 +1,121 @@
|
||||
#####################################################################################
|
||||
#
|
||||
# Copyright (c) Harry Pierson. All rights reserved.
|
||||
#
|
||||
# This source code is subject to terms and conditions of the Microsoft Public License.
|
||||
# A copy of the license can be found at http://opensource.org/licenses/ms-pl.html
|
||||
# By using this source code in any fashion, you are agreeing to be bound
|
||||
# by the terms of the Microsoft Public License.
|
||||
#
|
||||
# You must not remove this notice, or any other, from this software.
|
||||
#
|
||||
#####################################################################################
|
||||
|
||||
import ipypulldom
|
||||
from System.Xml import XmlNodeType
|
||||
|
||||
class _type_factory(object):
|
||||
class _type_node(object):
|
||||
def __init__(self, node):
|
||||
ty = type(node)
|
||||
self.name = ty.__name__
|
||||
self.namespace = ty.xmlns
|
||||
|
||||
def __init__(self):
|
||||
self.types = {}
|
||||
|
||||
def find_type(self, node, parent):
|
||||
def create_type(node, parent):
|
||||
return type(node.name, (parent,), {'xmlns':node.namespace})
|
||||
|
||||
if parent not in self.types:
|
||||
self.types[parent] = {}
|
||||
|
||||
tp = self.types[parent]
|
||||
if node.name not in tp:
|
||||
tp[node.name] = [create_type(node, parent)]
|
||||
|
||||
tpn = tp[node.name]
|
||||
|
||||
for t in tpn:
|
||||
if t.xmlns == node.namespace:
|
||||
return t
|
||||
|
||||
#if there's no matching namespace type, create one and add it to the list
|
||||
new_type = create_type(node, parent)
|
||||
tpn.append(new_type)
|
||||
return new_type
|
||||
|
||||
def __call__(self, node, parent=object):
|
||||
if isinstance(node, ipypulldom.XmlNode):
|
||||
return self.find_type(node, parent)
|
||||
return self.find_type(self._type_node(node), parent)
|
||||
|
||||
|
||||
xtype = _type_factory()
|
||||
|
||||
|
||||
def xml2py(nodelist):
|
||||
|
||||
def children(nodelist):
|
||||
while True:
|
||||
child = xml2py(nodelist)
|
||||
if child is None:
|
||||
break
|
||||
yield child
|
||||
|
||||
def set_attribute(parent, child):
|
||||
name = type(child).__name__
|
||||
if not hasattr(parent, name):
|
||||
setattr(parent, name, child)
|
||||
else:
|
||||
val = getattr(parent, name)
|
||||
if isinstance(val, list):
|
||||
val.append(child)
|
||||
else:
|
||||
setattr(parent, name, [val, child])
|
||||
|
||||
node = nodelist.next()
|
||||
if node.nodeType == XmlNodeType.EndElement:
|
||||
return None
|
||||
|
||||
elif node.nodeType == XmlNodeType.Text or node.nodeType == XmlNodeType.CDATA:
|
||||
return node.value
|
||||
|
||||
elif node.nodeType == XmlNodeType.Element:
|
||||
|
||||
#create a new object type named for the element name
|
||||
cur = xtype(node)()
|
||||
cur._nodetype = XmlNodeType.Element
|
||||
|
||||
#collect all the attributes and children in lists
|
||||
attributes = [xtype(attr, str)(attr.value) for attr in node.attributes]
|
||||
children = [child for child in children(nodelist)]
|
||||
|
||||
if len(children) == 1 and isinstance(children[0], str):
|
||||
#fold up elements with a single text node
|
||||
cur = xtype(cur, str)(children[0])
|
||||
cur._nodetype = XmlNodeType.Element
|
||||
else:
|
||||
#otherwise, add child elements as properties on the current node
|
||||
for child in children:
|
||||
set_attribute(cur, child)
|
||||
|
||||
for attr in attributes:
|
||||
attr._nodetype = XmlNodeType.Attribute
|
||||
set_attribute(cur, attr)
|
||||
|
||||
return cur
|
||||
|
||||
|
||||
def parse(xml):
|
||||
return xml2py(ipypulldom.parse(xml))
|
||||
|
||||
def parseString(xml):
|
||||
return xml2py(ipypulldom.parseString(xml))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
rss = parse('http://feeds.feedburner.com/Devhawk')
|
||||
for item in rss.channel.item:
|
||||
print item.title
|
||||
Reference in New Issue
Block a user