1.1 --- a/vContent.py Fri Oct 17 00:40:32 2008 +0200
1.2 +++ b/vContent.py Fri Oct 17 22:58:43 2008 +0200
1.3 @@ -246,17 +246,15 @@
1.4 else:
1.5 return value
1.6
1.7 -class Parser:
1.8 +class ParserBase:
1.9
1.10 - "A parser for content in vCard/vCalendar/iCalendar-like formats."
1.11 + "An abstract parser for content in vCard/vCalendar/iCalendar-like formats."
1.12
1.13 def __init__(self):
1.14
1.15 "Initialise the parser."
1.16
1.17 - self.elements = [] # also known as components
1.18 - self.document = []
1.19 - self.current = self.document
1.20 + self.names = []
1.21
1.22 def parse(self, f):
1.23
1.24 @@ -266,36 +264,89 @@
1.25
1.26 for name, parameters, value in parser:
1.27
1.28 - # Add new elements/components to the current position in the
1.29 - # document, recording the element as the active element.
1.30 -
1.31 if name == "BEGIN":
1.32 - children = []
1.33 - element = (value, parameters, children)
1.34 - self.elements.append(element)
1.35 - self.current.append(element)
1.36 - self.current = children
1.37 -
1.38 - # End elements by removing them from the active element stack and
1.39 - # making the next element's children the current position for new
1.40 - # content.
1.41 + self.names.append(value)
1.42 + self.startElement(value, parameters)
1.43
1.44 elif name == "END":
1.45 - start_element = self.elements.pop()
1.46 - start_value, start_parameters, children = start_element
1.47 - if start_value != value:
1.48 + start_name = self.names.pop()
1.49 + if start_name != value:
1.50 raise ParseError, "Mismatch in BEGIN and END declarations (%r and %r) at line %d." % (
1.51 - start_value, value, f.line_number)
1.52 - if self.elements:
1.53 - parent_value, parent_parameters, children = self.elements[-1]
1.54 - self.current = children
1.55 - else:
1.56 - self.current = self.document
1.57 + start_name, value, f.line_number)
1.58 +
1.59 + self.endElement(value)
1.60
1.61 else:
1.62 - self.current.append((name, parameters, value))
1.63 + self.handleComponent(name, parameters, value)
1.64 +
1.65 +class Parser(ParserBase):
1.66 +
1.67 + "A SAX-like parser for vCard/vCalendar/iCalendar-like formats."
1.68 +
1.69 + def __init__(self):
1.70 + ParserBase.__init__(self)
1.71 + self.elements = [] # also known as components
1.72 +
1.73 + def startElement(self, name, parameters):
1.74 +
1.75 + """
1.76 + Add the element/component with the given 'name' and 'parameters',
1.77 + recording an empty list of children as part of the element's content.
1.78 + """
1.79 +
1.80 + element = self.handleComponent(name, parameters, [])
1.81 + self.elements.append(element)
1.82 + return element
1.83 +
1.84 + def endElement(self, name):
1.85 +
1.86 + """
1.87 + End the element with the given 'name' by removing it from the active
1.88 + element stack.
1.89 + """
1.90 +
1.91 + if len(self.elements) > 1:
1.92 + return self.elements.pop()
1.93 + elif self.elements:
1.94 + return self.elements[-1]
1.95 +
1.96 + def handleComponent(self, name, parameters, value):
1.97
1.98 - return self.document
1.99 + """
1.100 + Record the component with the given 'name', 'parameters' and 'value' as
1.101 + part of the current element's children.
1.102 + """
1.103 +
1.104 + component = self.makeComponent(name, parameters, value)
1.105 + self.attachComponent(component)
1.106 + return component
1.107 +
1.108 + # Component object construction/manipulation methods.
1.109 +
1.110 + def attachComponent(self, component):
1.111 +
1.112 + "Attach the given 'component' to its parent."
1.113 +
1.114 + if self.elements:
1.115 + element_name, element_parameters, element_children = self.elements[-1]
1.116 + element_children.append(component)
1.117 +
1.118 + def makeComponent(self, name, parameters, value):
1.119 +
1.120 + """
1.121 + Make a component object from the given 'name', 'parameters' and 'value'.
1.122 + """
1.123 +
1.124 + return (name, parameters, value)
1.125 +
1.126 + # Public methods.
1.127 +
1.128 + def parse(self, f):
1.129 +
1.130 + "Parse the contents of the file 'f'."
1.131 +
1.132 + ParserBase.parse(self, f)
1.133 + return self.elements[0]
1.134
1.135 # Public functions.
1.136