11import abc
22from enum import Enum
3- from typing import Any , Callable , Dict , Generic , List , Optional , Sequence , TypeVar
3+ from typing import Any , Callable , Dict , Generic , List , Optional , Sequence , Tuple , TypeVar
44
55from pydantic_xml .typedefs import NsMap
66
@@ -52,14 +52,6 @@ def find_element(
5252 :return: xml element
5353 """
5454
55- @abc .abstractmethod
56- def get_text (self ) -> Optional [str ]:
57- """
58- Returns the element text.
59-
60- :return: element text
61- """
62-
6355 @abc .abstractmethod
6456 def pop_text (self ) -> Optional [str ]:
6557 """
@@ -78,14 +70,6 @@ def pop_attrib(self, name: str) -> Optional[str]:
7870 :return: element attribute
7971 """
8072
81- @abc .abstractmethod
82- def get_attributes (self ) -> Optional [Dict [str , str ]]:
83- """
84- Returns the element attributes.
85-
86- :return: element attributes
87- """
88-
8973 @abc .abstractmethod
9074 def pop_attributes (self ) -> Optional [Dict [str , str ]]:
9175 """
@@ -115,14 +99,6 @@ def find_sub_element(self, path: Sequence[str], search_mode: 'SearchMode') -> Op
11599 :return: found element or `None`
116100 """
117101
118- @abc .abstractmethod
119- def get_elements (self ) -> Optional [List ['XmlElement[Any]' ]]:
120- """
121- Returns the element sub-elements.
122-
123- :return: sub-element
124- """
125-
126102 @abc .abstractmethod
127103 def create_snapshot (self ) -> 'XmlElement[Any]' :
128104 """
@@ -145,6 +121,14 @@ def to_native(self) -> Any:
145121 :return: native element
146122 """
147123
124+ @abc .abstractmethod
125+ def get_unbound (self ) -> List [Tuple [Tuple [str , ...], str ]]:
126+ """
127+ Returns unbound entities.
128+
129+ :return: list of unbound entities
130+ """
131+
148132
149133class XmlElementWriter (abc .ABC ):
150134 """
@@ -251,7 +235,7 @@ def __init__(
251235 self .elements = elements
252236 self .next_element_idx = next_element_idx
253237
254- __slots__ = ('_tag' , '_nsmap' )
238+ __slots__ = ('_tag' , '_nsmap' , '_state' )
255239
256240 @classmethod
257241 @abc .abstractmethod
@@ -337,9 +321,6 @@ def append_element(self, element: 'XmlElement[NativeElement]') -> None:
337321 def get_attrib (self , name : str ) -> Optional [str ]:
338322 return self ._state .attrib .get (name , None ) if self ._state .attrib else None
339323
340- def get_text (self ) -> Optional [str ]:
341- return self ._state .text
342-
343324 def pop_text (self ) -> Optional [str ]:
344325 result , self ._state .text = self ._state .text , None
345326
@@ -348,9 +329,6 @@ def pop_text(self) -> Optional[str]:
348329 def pop_attrib (self , name : str ) -> Optional [str ]:
349330 return self ._state .attrib .pop (name , None ) if self ._state .attrib else None
350331
351- def get_attributes (self ) -> Optional [Dict [str , str ]]:
352- return self ._state .attrib
353-
354332 def pop_attributes (self ) -> Optional [Dict [str , str ]]:
355333 result , self ._state .attrib = self ._state .attrib , None
356334
@@ -395,8 +373,20 @@ def find_element(
395373
396374 return searcher (self ._state , tag , look_behind , step_forward )
397375
398- def get_elements (self ) -> Optional [List ['XmlElement[NativeElement]' ]]:
399- return self ._state .elements [self ._state .next_element_idx :]
376+ def get_unbound (self , path : Tuple [str , ...] = ()) -> List [Tuple [Tuple [str , ...], str ]]:
377+ result : List [Tuple [Tuple [str , ...], str ]] = []
378+
379+ if self ._state .text and (text := self ._state .text .strip ()):
380+ result .append ((path , text ))
381+
382+ if attrs := self ._state .attrib :
383+ for name , value in attrs .items ():
384+ result .append ((path + (f'@{ name } ' ,), value ))
385+
386+ for sub_element in self ._state .elements :
387+ result .extend (sub_element .get_unbound (path + (sub_element .tag ,)))
388+
389+ return result
400390
401391
402392class SearchMode (str , Enum ):
0 commit comments