88Contains an event-driven builder for dictionary based (JSON-like) structure
99"""
1010import re
11- from .common import ATTRIB_SUFFIX , HSD_ATTRIB_SUFFIX
11+ from .common import ATTRIB_SUFFIX , HSD_ATTRIB_SUFFIX , HsdError
1212from .eventhandler import HsdEventHandler
1313
1414
@@ -40,9 +40,9 @@ def __init__(self, flatten_data: bool = False,
4040 include_hsd_attribs : bool = False ):
4141 super ().__init__ ()
4242 self ._hsddict = {}
43- self ._curblock = self ._hsddict
43+ self ._content = self ._hsddict # Content obtained for the current node
4444 self ._parentblocks = []
45- self ._data = None
45+ self ._attribs = []
4646 self ._flatten_data = flatten_data
4747 self ._include_hsd_attribs = include_hsd_attribs
4848
@@ -54,34 +54,51 @@ def hsddict(self):
5454
5555
5656 def open_tag (self , tagname , attrib , hsdattrib ):
57- if attrib is not None :
58- self ._curblock [tagname + ATTRIB_SUFFIX ] = attrib
59- if self ._include_hsd_attribs and hsdattrib is not None :
60- self ._curblock [tagname + HSD_ATTRIB_SUFFIX ] = hsdattrib
61- self ._parentblocks .append (self ._curblock )
62- self ._curblock = {}
57+ self ._attribs .append ((attrib , hsdattrib ))
58+ content = {} if self ._content is None else self ._content
59+ self ._parentblocks .append (content )
60+ self ._content = None
6361
6462
6563 def close_tag (self , tagname ):
64+ attrib , hsdattrib = self ._attribs .pop (- 1 )
6665 parentblock = self ._parentblocks .pop (- 1 )
67- prevcontent = parentblock .get (tagname )
68- if prevcontent is not None and not isinstance (prevcontent , list ):
69- prevcontent = [prevcontent ]
70- parentblock [tagname ] = prevcontent
71- if self ._data is None :
72- content = self ._curblock
73- else :
74- content = self ._data
75- self ._data = None
76- if prevcontent is None :
66+ prevcont = parentblock .get (tagname )
67+ if prevcont is not None :
68+ if isinstance (prevcont , dict ) and isinstance (self ._content , dict ):
69+ prevcont = [prevcont ]
70+ parentblock [tagname ] = prevcont
71+ elif not (isinstance (prevcont , list )
72+ and isinstance (prevcont [0 ], dict )):
73+ msg = f"Invalid duplicate occurance of node '{ tagname } '"
74+ raise HsdError (msg )
75+ content = {} if self ._content is None else self ._content
76+ if prevcont is None :
7777 parentblock [tagname ] = content
78+ if attrib :
79+ parentblock [tagname + ATTRIB_SUFFIX ] = attrib
80+ if self ._include_hsd_attribs :
81+ parentblock [tagname + HSD_ATTRIB_SUFFIX ] = hsdattrib
7882 else :
79- prevcontent .append (content )
80- self ._curblock = parentblock
83+ prevcont .append (content )
84+ prevattrib = parentblock .get (tagname + ATTRIB_SUFFIX )
85+ if not (prevattrib is None and attrib is None ):
86+ msg = f"Duplicate node '{ tagname } ' should not carry attributes"
87+ if self ._include_hsd_attribs :
88+ prevhsdattrib = parentblock .get (tagname + HSD_ATTRIB_SUFFIX )
89+ if isinstance (prevhsdattrib , list ):
90+ prevhsdattrib .append (hsdattrib )
91+ else :
92+ parentblock [tagname + HSD_ATTRIB_SUFFIX ] = [prevhsdattrib ,
93+ hsdattrib ]
94+ self ._content = parentblock
8195
8296
8397 def add_text (self , text ):
84- self ._data = self ._text_to_data (text )
98+ if self ._content is not None :
99+ msg = f"Data appeared in an invalid context"
100+ raise HsdError (msg )
101+ self ._content = self ._text_to_data (text )
85102
86103
87104 def _text_to_data (self , txt ):
0 commit comments