import xml.dom.minidom as mdom from typing import List, Tuple, Dict from enum import Enum from frame.ReferView import EmptyNode, MemoryNode class FragmentSlice(EmptyNode): def __init__(self, def_mark: bool = False, name: str= ""): self.is_define_node = (def_mark, name) self.parent_story = "" self.story_refer = "" self.fragm_refer = "" self.fragm_sort_i = 0 self.prev_node: 'FragmentSlice' = None # 上游节点 self.next_node: 'FragmentSlice' = None # 下游节点 self.refers_slice: Dict[str, 'FragmentSlice'] = {} # 引用切面 self.text_sections: List[str] = [] # 文本段落 pass def get_from_memory(self) -> str: return "\n".join(self.text_sections) pass def set_to_memory(self, content: str): self.text_sections = content.split("\n") pass class StoryMap: def __init__(self, name: str): self.story_name = name self.sort_index = 0 self.empty_head = FragmentSlice() self.slice_list: List[FragmentSlice] = [self.empty_head] pass def append_fragment_slice(self, node: FragmentSlice): self.slice_list[-1].next_node = node node.parent_story = self.story_name node.prev_node = self.slice_list[-1] node.fragm_sort_i = len(self.slice_list) self.slice_list.append(node) pass def get_fragment_defined(self, name: str) -> FragmentSlice: for fit in self.slice_list: if fit.is_define_node[0]: if fit.is_define_node[1] == name: return fit pass pass return None class XAST_ParseTool: def __init__(self, ast_path: str): self.dom_tree = mdom.parse(ast_path) self.story_list: List[StoryMap] = [] names = self.story_names() for nm in names: vinst = self.__extract_empty_storymap(nm) self.__storynode_initfrags(vinst[0], vinst[1]) self.story_list.append(vinst[0]) pass def story_names(self) -> List[str]: """ 获取所有故事名称 :return: List[故事名] """ storys = self.dom_tree.getElementsByTagName("story") values = [] for n in storys: values.append(n.getAttribute("name")) pass return values def __extract_empty_storymap(self, name: str) -> Tuple[StoryMap, mdom.Element]: storys = self.dom_tree.getElementsByTagName("story") for node in storys: if node.getAttribute("name") == name: mem_node = StoryMap(name) mem_node.sort_index = int(node.getAttribute("sort")) return (mem_node, node) pass return None def __storynode_initfrags(self, node: StoryMap, e: mdom.Element): first_elem: mdom.Element = e.firstChild while first_elem != None: if hasattr(first_elem, "tagName"): dom_tag = first_elem.tagName if first_elem.tagName == "fragment": fnode = FragmentSlice(True, first_elem.getAttribute("name")) self.__fragmnode_init_desc(fnode, first_elem) node.append_fragment_slice(fnode) elif first_elem.tagName == "refer": fnode = FragmentSlice() fnode.story_refer = first_elem.getAttribute("story") fnode.fragm_refer = first_elem.getAttribute("fragment") self.__fragmnode_init_desc(fnode, first_elem) node.append_fragment_slice(fnode) pass pass first_elem = first_elem.nextSibling pass def __fragmnode_init_desc(self, node: FragmentSlice, e: mdom.Element): node_elem: mdom.Element = e.firstChild while node_elem != None: if hasattr(node_elem, "tagName") and node_elem.tagName == "text-section": line = node_elem.getAttribute("text") node.text_sections.append(line) pass node_elem = node_elem.nextSibling pass pass def storylines_plait(self, storys: Dict[str, StoryMap]): for snode in storys.values(): self.__storyline_plait_within(snode, storys) pass def __storyline_plait_within(self, story: StoryMap, storys_map: Dict[str, StoryMap]): for fnode in story.slice_list[1:]: if not fnode.is_define_node[0]: sname = fnode.story_refer fname = fnode.fragm_refer target_story = storys_map[sname] target_fragment = target_story.get_fragment_defined(fname) target_fragment.refers_slice[story.story_name] = fnode pass pass pass pass def storyline_list2map(storylines: List[StoryMap]) -> Dict[str, StoryMap]: retv = {} for linst in storylines: retv[linst.story_name] = linst pass return retv