Parse a table node.

        :param node: The lxml table node to parse
        :param state: The global state necessary to place the node in context
            of the document as a whole.
5196
def _parse_table(self, node, state):
        
        if not self.tabular:
            logger.error("Called _parse_table without tabular activated.")
            return state

        if node.tag == "table":
            table_idx = state["table"]["idx"]
            stable_id = f"{state['document'].name}::{'table'}:{state['table']['idx']}"

            # Set name for Table
            name = node.attrib["name"] if "name" in node.attrib else None

            # Create the Table in the DB
            parts = {}
            parts["document"] = state["document"]
            parts["stable_id"] = stable_id
            parts["name"] = name
            parts["position"] = table_idx
            parent = state["parent"][node]
            if isinstance(parent, Cell):
                parts["section"] = parent.table.section
            elif isinstance(parent, Section):
                parts["section"] = parent
            else:
                raise NotImplementedError("Table is not within a Section or Cell")

            state["context"][node] = Table(**parts)

            # Local state for each table. This is required to support nested
            # tables
            state["table"][table_idx] = {
                "grid": defaultdict(int),
                "cell_pos": 0,
                "row_idx": -1,
                "col_idx": 0,
            }

            # Increment table counter
            state["table"]["idx"] += 1

        elif node.tag == "tr":
            if not isinstance(state["parent"][node], Table):
                raise NotImplementedError("Table row parent must be a Table.")

            state["table"][state["parent"][node].position]["col_idx"] = 0
            state["table"][state["parent"][node].position]["row_idx"] += 1

        elif node.tag in ["td", "th"]:
            if not isinstance(state["parent"][node], Table):
                raise NotImplementedError("Cell parent must be a Table.")

            if not state["table"][state["parent"][node].position]["row_idx"] >= 0:
                raise NotImplementedError("Table cell encountered before a table row.")

            # calculate row_start/col_start
            while state["table"][state["parent"][node].position]["grid"][
                (
                    state["table"][state["parent"][node].position]["row_idx"],
                    state["table"][state["parent"][node].position]["col_idx"],
                )
            ]:  # while a cell on the grid is occupied, keep moving
                state["table"][state["parent"][node].position]["col_idx"] += 1
            col_start = state["table"][state["parent"][node].position]["col_idx"]
            row_start = state["table"][state["parent"][node].position]["row_idx"]

            # calculate row_end/col_end
            row_end = row_start
            if "rowspan" in node.attrib:
                try:
                    row_end += int(node.get("rowspan")) - 1
                except ValueError:
                    logger.error(f"Rowspan has invalid value: '{node.get('rowspan')}'")

            col_end = col_start
            if "colspan" in node.attrib:
                try:
                    col_end += int(node.get("colspan")) - 1
                except ValueError:
                    logger.error(f"Colspan has invalid value: '{node.get('colspan')}'")

            # update grid with occupied cells
            for r, c in itertools.product(
                list(range(row_start, row_end + 1)), list(range(col_start, col_end + 1))
            ):
                state["table"][state["parent"][node].position]["grid"][(r, c)] = 1

            # Set name for Cell
            name = node.attrib["name"] if "name" in node.attrib else None

            # construct cell
            parts = defaultdict(list)
            parts["document"] = state["document"]
            parts["name"] = name
            parts["table"] = state["parent"][node]
            parts["row_start"] = row_start
            parts["row_end"] = row_end
            parts["col_start"] = col_start
            parts["col_end"] = col_end
            parts["position"] = state["table"][state["parent"][node].position][
                "cell_pos"
            ]
            stable_id = (
                f"{parts['document'].name}"
                f"::"
                f"{'cell'}"
                f":"
                f"{parts['table'].position}"
                f":"
                f"{row_start}"
                f":"
                f"{col_start}"
            )
            parts["stable_id"] = stable_id
            # Create the Cell in the DB
            state["context"][node] = Cell(**parts)

            # Update position
            state["table"][state["parent"][node].position]["col_idx"] += 1
            state["table"][state["parent"][node].position]["cell_pos"] += 1

        return state
1257490
def _parse_sentence(self, paragraph, node, state):
        
        text = state["paragraph"]["text"]
        field = state["paragraph"]["field"]

        # Set name for Sentence
        name = node.attrib["name"] if "name" in node.attrib else None

        # Lingual Parse
        document = state["document"]
        for parts in self.tokenize_and_split_sentences(text):
            parts["document"] = document
            # NOTE: Why do we overwrite this from the spacy parse?
            parts["position"] = state["sentence"]["idx"]
            abs_sentence_offset_end = (
                state["sentence"]["abs_offset"]
                + parts["char_offsets"][-1]
                + len(parts["words"][-1])
            )
            parts["stable_id"] = construct_stable_id(
                document,
                "sentence",
                state["sentence"]["abs_offset"],
                abs_sentence_offset_end,
            )
            parts["name"] = name
            state["sentence"]["abs_offset"] = abs_sentence_offset_end
            if self.structural:
                context_node = node.getparent() if field == "tail" else node
                tree = lxml.etree.ElementTree(state["root"])
                parts["xpath"] = tree.getpath(context_node)
                parts["html_tag"] = context_node.tag
                parts["html_attrs"] = [
                    "=".join(x) for x in list(context_node.attrib.items())
                ]

                # Extending html style attribute with the styles
                # from inline style class for the element.
                cur_style_index = None
                for index, attr in enumerate(parts["html_attrs"]):
                    if attr.find("style") >= 0:
                        cur_style_index = index
                        break
                head = state["root"].find("head")
                styles = None
                if head is not None:
                    styles = head.find("style")
                if styles is not None:
                    for x in list(context_node.attrib.items()):
                        if x[0] == "class":
                            exp = r"(." + x[1] + r")([\n\s\r]*)\{(.*?)\}"
                            r = re.compile(exp, re.DOTALL)
                            if r.search(styles.text) is not None:
                                if cur_style_index is not None:
                                    parts["html_attrs"][cur_style_index] += (
                                        r.search(styles.text)
                                        .group(3)
                                        .replace("\r", "")
                                        .replace("\n", "")
                                        .replace("\t", "")
                                    )
                                else:
                                    parts["html_attrs"].extend(
                                        [
                                            "style="
                                            + re.sub(
                                                r"\s{1,}",
                                                " ",
                                                r.search(styles.text)
                                                .group(3)
                                                .replace("\r", "")
                                                .replace("\n", "")
                                                .replace("\t", "")
                                                .strip(),
                                            )
                                        ]
                                    )
                            break
            if self.tabular:
                parts["position"] = state["sentence"]["idx"]

                # If tabular, consider own Context first in case a Cell
                # was just created. Otherwise, defer to the parent.
                parent = paragraph
                if isinstance(parent, Paragraph):
                    parts["section"] = parent.section
                    parts["paragraph"] = parent
                    if parent.cell:
                        parts["table"] = parent.cell.table
                        parts["cell"] = parent.cell
                        parts["row_start"] = parent.cell.row_start
                        parts["row_end"] = parent.cell.row_end
                        parts["col_start"] = parent.cell.col_start
                        parts["col_end"] = parent.cell.col_end
                else:
                    raise NotImplementedError("Sentence parent must be Paragraph.")
            yield Sentence(**parts)
            state["sentence"]["idx"] += 1
1226777
def parse(node)
      link_to_table_part_xml = OOXMLDocumentObject.get_link_from_rels(node.attribute('id').value)
      doc = parse_xml(OOXMLDocumentObject.path_to_folder + link_to_table_part_xml.gsub('..', 'xl'))
      table_node = doc.xpath('xmlns:table').first
      table_node.attributes.each do |key, value|
        case key
        when 'name'
          @name = value.value.to_s
        when 'displayName'
          @display_name = value.value.to_s
        when 'ref'
          @reference = Coordinates.parser_coordinates_range value.value.to_s
        end
      end
      table_node.xpath('*').each do |node_child|
        case node_child.name
        when 'autoFilter'
          @autofilter = Autofilter.new(parent: self).parse(node_child)
        when 'extLst'
          @extension_list = ExtensionList.new(parent: self).parse(node_child)
        when 'tableColumns'
          @table_columns = TableColumns.new(parent: self).parse(node_child)
        when 'tableStyleInfo'
          @table_style_info = TableStyleInfo.new(parent: self).parse(node_child)
        end
      end
      self
    end
1289933
def parse(node)
      list = []
      node.xpath('*').each do |node_child|
        case node_child.name
        when 'AlternateContent'
          list << AlternateContent.new(parent: self).parse(node_child)
        end
      end
      list
    end
150806
def parse(self, node):
        
        self._attrs = {}
        vals = []
        yielded = False

        for x in self._read_parts(node):
            if isinstance(x, Field):
                yielded = True
                x.attrs = self._attrs
                yield x
            else:
                vals.append(ustr(x).strip(' \n\t'))

        joined = ' '.join([ x for x in vals if x ])
        if joined:
            yielded = True
            yield Field(node, guess_type(joined), self._attrs)

        if not yielded:
            yield Field(node, "", self._attrs)
30440
def parse(node)
      node.xpath('*').each do |node_child|
        case node_child.name
        when 'trHeight'
          @height = TableRowHeight.new(parent: self).parse(node_child)
        when 'tblCellSpacing'
          @cells_spacing = OoxmlSize.new.parse(node_child)
        when 'tblHeader'
          @table_header = option_enabled?(node_child)
        end
      end
      self
    end
573703
def parse(node)
      node.xpath('*').each do |grid_child|
        case grid_child.name
        when 'gridCol'
          @columns << GridColumn.new(parent: self).parse(grid_child)
        end
      end
      self
    end
111891
def parse(node)
      node.xpath('*').each do |node_child|
        case node_child.name
        when 'blip'
          @file_reference = FileReference.new(parent: self).parse(node_child)
        when 'tile'
          @tile = Tile.new(OOXMLCoordinates.parse(node_child, x_attr: 'tx', y_attr: 'ty'),
                           OOXMLCoordinates.parse(node_child, x_attr: 'sx', y_attr: 'sy'),
                           parent: self).parse(node_child)
        end
      end
      self
    end
1171316
def parse(node)
      node.attributes.each do |key, value|
        case key
        when 'type'
          @type = value.value.to_sym
        when 'styleId'
          @style_id = value.value
        when 'default'
          @default = attribute_enabled?(value.value)
        end
      end
      node.xpath('*').each do |subnode|
        case subnode.name
        when 'name'
          @name = subnode.attribute('val').value
        when 'basedOn'
          @based_on = subnode.attribute('val').value
        when 'next'
          @next_style = subnode.attribute('val').value
        when 'rPr'
          @run_properties = DocxParagraphRun.new(parent: self).parse_properties(subnode)
        when 'pPr'
          @paragraph_properties = ParagraphProperties.new(parent: self).parse(subnode)
        when 'tblPr'
          @table_properties = TableProperties.new(parent: self).parse(subnode)
        when 'trPr'
          @table_row_properties = TableRowProperties.new(parent: self).parse(subnode)
        when 'tcPr'
          @table_cell_properties = CellProperties.new(parent: self).parse(subnode)
        when 'tblStylePr'
          @table_style_properties_list << TableStyleProperties.new(parent: self).parse(subnode)
        when 'qFormat'
          @q_format = true
        end
      end
      fill_empty_table_styles
      self
    end
42115
def parse(node)
      node.xpath('*').each do |node_child|
        case node_child.name
        when 'tnLst'
          @time_node_list = TimeNode.parse_list(node_child)
        end
      end
      self
    end
746979
def parse(node)
      node.xpath('*').each do |node_child|
        case node_child.name
        when 'rPr'
          @properties = RunProperties.new(parent: self).parse(node_child)
        when 't'
          @t = Text.new(parent: self).parse(node_child)
          @text = t.text
        when 'tab'
          @tab = Tab.new(parent: self).parse(node_child)
        end
      end
      self
    end
831088
def parse(node)
      node.attributes.each do |key, value|
        case key
        when 'w'
          @width = value.value.to_f
        when 'h'
          @height = value.value.to_f
        when 'stroke'
          @stroke = value.value.to_f
        end
      end
      node.xpath('*').each do |node_child|
        @elements << DocxShapeLineElement.new(parent: self).parse(node_child)
      end
      self
    end
46561
def parse(node)
      node.xpath('*').each do |node_child|
        case node_child.name
        when 'name'
          @name = node_child.attribute('val').value
        when 'qFormat'
          @q_format = option_enabled?(node_child)
        end
      end
      self
    end
1357521
def parse_xml(self, node):
        
        self._set_properties(node)
        self.name = node.get('name', None)
        self.opacity = node.get('opacity', self.opacity)
        self.visible = node.get('visible', self.visible)
        image_node = node.find('image')
        self.source = image_node.get('source', None)
        self.trans = image_node.get('trans', None)
        return self
282658
def parse(node)
      node.xpath('*').each do |node_child|
        case node_child.name
        when 'nvSpPr'
          @non_visual_properties = NonVisualShapeProperties.new(parent: self).parse(node_child)
        when 'spPr'
          @properties = DocxShapeProperties.new(parent: self).parse(node_child)
        when 'txbx'
          @text_body = OOXMLTextBox.new(parent: self).parse(node_child)
        when 'txBody'
          @text_body = TextBody.new(parent: self).parse(node_child)
        when 'bodyPr'
          @body_properties = OOXMLShapeBodyProperties.new(parent: self).parse(node_child)
        end
      end
      self
    end
1228438
def parse(node)
      node.attributes.each do |key, value|
        case key
        when 'leftFromText'
          @left = OoxmlSize.new(value.value.to_f)
        when 'rightFromText'
          @right = OoxmlSize.new(value.value.to_f)
        when 'topFromText'
          @top = OoxmlSize.new(value.value.to_f)
        when 'bottomFromText'
          @bottom = OoxmlSize.new(value.value.to_f)
        when 'tblpX'
          @position_x = OoxmlSize.new(value.value.to_f)
        when 'tblpY'
          @position_y = OoxmlSize.new(value.value.to_f)
        when 'vertAnchor'
          @vertical_anchor = value.value.to_sym
        when 'horzAnchor'
          @horizontal_anchor = value.value.to_sym
        when 'tblpXSpec'
          @horizontal_align_from_anchor = value.value.to_sym
        when 'tblpYSpec'
          @vertical_align_from_anchor = value.value.to_sym
        end
      end
      self
    end
1092336
def parse(self, *nodes):
        
        for n in nodes:
            if not n.contents:
                continue
            row = self._parse(n)
            if not row.is_null:
                yield row