tools/xmlparser: implement writer
This commit is contained in:
parent
f16dedb320
commit
39056cf358
|
@ -1,5 +1,6 @@
|
|||
import unittest
|
||||
|
||||
import io
|
||||
import xml.parsers.expat
|
||||
|
||||
from nemubot.tools.xmlparser import XMLParser
|
||||
|
@ -12,6 +13,11 @@ class StringNode():
|
|||
def characters(self, content):
|
||||
self.string += content
|
||||
|
||||
def saveElement(self, store, tag="string"):
|
||||
store.startElement(tag, {})
|
||||
store.characters(self.string)
|
||||
store.endElement(tag)
|
||||
|
||||
|
||||
class TestNode():
|
||||
def __init__(self, option=None):
|
||||
|
@ -22,6 +28,15 @@ class TestNode():
|
|||
self.mystr = child.string
|
||||
return True
|
||||
|
||||
def saveElement(self, store, tag="test"):
|
||||
store.startElement(tag, {"option": self.option})
|
||||
|
||||
strNode = StringNode()
|
||||
strNode.string = self.mystr
|
||||
strNode.saveElement(store)
|
||||
|
||||
store.endElement(tag)
|
||||
|
||||
|
||||
class Test2Node():
|
||||
def __init__(self, option=None):
|
||||
|
@ -33,6 +48,15 @@ class Test2Node():
|
|||
self.mystrs.append(attrs["value"])
|
||||
return True
|
||||
|
||||
def saveElement(self, store, tag="test"):
|
||||
store.startElement(tag, {"option": self.option} if self.option is not None else {})
|
||||
|
||||
for mystr in self.mystrs:
|
||||
store.startElement("string", {"value": mystr})
|
||||
store.endElement("string")
|
||||
|
||||
store.endElement(tag)
|
||||
|
||||
|
||||
class TestXMLParser(unittest.TestCase):
|
||||
|
||||
|
@ -44,9 +68,11 @@ class TestXMLParser(unittest.TestCase):
|
|||
p.CharacterDataHandler = mod.characters
|
||||
p.EndElementHandler = mod.endElement
|
||||
|
||||
p.Parse("<string>toto</string>", 1)
|
||||
inputstr = "<string>toto</string>"
|
||||
p.Parse(inputstr, 1)
|
||||
|
||||
self.assertEqual(mod.root.string, "toto")
|
||||
self.assertEqual(mod.saveDocument(header=False).getvalue(), inputstr)
|
||||
|
||||
|
||||
def test_parser2(self):
|
||||
|
@ -57,10 +83,12 @@ class TestXMLParser(unittest.TestCase):
|
|||
p.CharacterDataHandler = mod.characters
|
||||
p.EndElementHandler = mod.endElement
|
||||
|
||||
p.Parse("<test option='123'><string>toto</string></test>", 1)
|
||||
inputstr = '<test option="123"><string>toto</string></test>'
|
||||
p.Parse(inputstr, 1)
|
||||
|
||||
self.assertEqual(mod.root.option, "123")
|
||||
self.assertEqual(mod.root.mystr, "toto")
|
||||
self.assertEqual(mod.saveDocument(header=False).getvalue(), inputstr)
|
||||
|
||||
|
||||
def test_parser3(self):
|
||||
|
@ -71,12 +99,14 @@ class TestXMLParser(unittest.TestCase):
|
|||
p.CharacterDataHandler = mod.characters
|
||||
p.EndElementHandler = mod.endElement
|
||||
|
||||
p.Parse("<test><string value='toto' /><string value='toto2' /></test>", 1)
|
||||
inputstr = '<test><string value="toto"/><string value="toto2"/></test>'
|
||||
p.Parse(inputstr, 1)
|
||||
|
||||
self.assertEqual(mod.root.option, None)
|
||||
self.assertEqual(len(mod.root.mystrs), 2)
|
||||
self.assertEqual(mod.root.mystrs[0], "toto")
|
||||
self.assertEqual(mod.root.mystrs[1], "toto2")
|
||||
self.assertEqual(mod.saveDocument(header=False, short_empty_elements=True).getvalue(), inputstr)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -134,6 +134,21 @@ class XMLParser:
|
|||
return
|
||||
raise TypeError(name + " tag not expected in " + self.display_stack())
|
||||
|
||||
def saveDocument(self, f=None, header=True, short_empty_elements=False):
|
||||
if f is None:
|
||||
import io
|
||||
f = io.StringIO()
|
||||
|
||||
import xml.sax.saxutils
|
||||
gen = xml.sax.saxutils.XMLGenerator(f, "utf-8", short_empty_elements=short_empty_elements)
|
||||
if header:
|
||||
gen.startDocument()
|
||||
self.root.saveElement(gen)
|
||||
if header:
|
||||
gen.endDocument()
|
||||
|
||||
return f
|
||||
|
||||
|
||||
def parse_file(filename):
|
||||
p = xml.parsers.expat.ParserCreate()
|
||||
|
|
|
@ -44,6 +44,13 @@ class ListNode:
|
|||
return self.items.__repr__()
|
||||
|
||||
|
||||
def saveElement(self, store, tag="list"):
|
||||
store.startElement(tag, {})
|
||||
for i in self.items:
|
||||
i.saveElement(store)
|
||||
store.endElement(tag)
|
||||
|
||||
|
||||
class DictNode:
|
||||
|
||||
"""XML node representing a Python dictionnnary
|
||||
|
@ -106,3 +113,16 @@ class DictNode:
|
|||
|
||||
def __repr__(self):
|
||||
return self.items.__repr__()
|
||||
|
||||
|
||||
def saveElement(self, store, tag="dict"):
|
||||
store.startElement(tag, {})
|
||||
for k, v in self.items.items():
|
||||
store.startElement("item", {"key": k})
|
||||
if isinstance(v, str):
|
||||
store.characters(v)
|
||||
else:
|
||||
for i in v:
|
||||
i.saveElement(store)
|
||||
store.endElement("item")
|
||||
store.endElement(tag)
|
||||
|
|
|
@ -53,6 +53,14 @@ class ParsingNode:
|
|||
return item in self.attrs
|
||||
|
||||
|
||||
def saveElement(self, store, tag=None):
|
||||
store.startElement(tag if tag is not None else self.tag, self.attrs)
|
||||
for child in self.children:
|
||||
child.saveElement(store)
|
||||
store.characters(self.content)
|
||||
store.endElement(tag if tag is not None else self.tag)
|
||||
|
||||
|
||||
class GenericNode(ParsingNode):
|
||||
|
||||
"""Consider all subtags as dictionnary
|
||||
|
|
Loading…
Reference in New Issue