Example #1
0
def add_ObjectN(N, metainf_manifest_xml_obj):
    """Add Object manifest:file-entry object to manifest.xml in META-INF of ods file"""

    NS = metainf_manifest_xml_obj.NS

    M = metainf_manifest_xml_obj.getroot()  # just to reduce line lengths

    # put subdirectory object into manifest
    obj_name = 'Object %i' % N
    attribD = {
        NS('manifest:full-path'): obj_name + '/',
        NS('manifest:media-type'): "application/vnd.oasis.opendocument.chart"
    }

    mfe = ET.Element(NS('manifest:file-entry'), attrib=attribD)
    M.insert(N, mfe)  # place in order

    # put xml files into subdirectory
    attribD = {
        NS('manifest:full-path'): obj_name + '/content.xml',
        NS('manifest:media-type'): "text/xml"
    }
    mfe = ET.Element(NS('manifest:file-entry'), attrib=attribD)
    M.insert(N * 3, mfe)  # place in order

    attribD = {
        NS('manifest:full-path'): obj_name + '/styles.xml',
        NS('manifest:media-type'): "text/xml"
    }
    mfe = ET.Element(NS('manifest:file-entry'), attrib=attribD)
    M.insert(N * 3, mfe)  # place in order
Example #2
0
    def new_elem(self, name, attribOD=None):
        """
        Create a new Element object.
        name format can be 'table:table' OR '{urn:oasis:names:tc:opendocument:xmlns:table:1.0}table'
        (i.e. can be path format OR tab format)
        attribOD is an OrderedDict in order to preserve attribute order.
        """

        tag = self.NS(name)
        #print( 'tag =',tag )

        if attribOD:
            OD = self.NS_attrib(attribOD)
            my_new_elem = ET.Element(tag, attrib=OD)
        else:
            my_new_elem = ET.Element(tag)

        sL = my_new_elem.tag.split('}')
        if len(sL) == 2:
            name = sL[1]
            uri = sL[0][1:]
            self.qnameOD[my_new_elem.tag] = '%s:%s' % (self.nsOD[uri], name)

        for qname, v in list(my_new_elem.attrib.items()):
            sL = qname.split('}')
            if len(sL) == 2:
                name = sL[1]
                uri = sL[0][1:]
                self.qnameOD[qname] = '%s:%s' % (self.nsOD[uri], name)

        return my_new_elem
Example #3
0
    def tostring(self):

        class dummy:
            pass
        xml_dataL = []
        if self.xml_header:
            xml_dataL = [self.xml_header + '\n']

        dummy_file = dummy()
        dummy_file.write = xml_dataL.append

        # There are differences between the python2 and python3 serialize routines
        if sys.version_info < (3,):
            ET._serialize_xml(dummy_file.write, self.root, "utf-8", self.qnameOD, self.nsOD)
        else:
            short_empty_elements = True # use short format for empty elements
            ET._serialize_xml(dummy_file.write, self.root, self.qnameOD, self.nsOD, short_empty_elements)

        return "".join(xml_dataL)
Example #4
0
    def tostring(self):
        class dummy:
            pass

        xml_dataL = []
        if self.xml_header:
            xml_dataL = [self.xml_header + '\n']

        dummy_file = dummy()
        dummy_file.write = xml_dataL.append

        # There are differences between the python2 and python3 serialize routines
        if sys.version_info < (3, ):
            ET._serialize_xml(dummy_file.write, self.root, "utf-8",
                              self.qnameOD, self.nsOD)
        else:
            short_empty_elements = True  # use short format for empty elements
            ET._serialize_xml(dummy_file.write, self.root, self.qnameOD,
                              self.nsOD, short_empty_elements)

        return "".join(xml_dataL)
Example #5
0
 def make_subelem(ndot1=1, ldot1='0.25in', ndot2=0, ldot2='0in', dist='0.03125in', style='rect'):
     """
     style can be "rect" or "round" (hard to tell the difference)
     """
     new_elem_2 = ET.SubElement(parent,"{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}stroke-dash", 
     attrib=OrderedDict([('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}name', '%s'%a_name), 
     ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}display-name', '%s'%display_name), 
     ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}style', '%s'%style), 
     ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}dots1', '%i'%ndot1), 
     ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}dots1-length', '%s'%ldot1), 
     ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}dots2', '%i'%ndot2), 
     ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}dots2-length', '%s'%ldot2), 
     ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}distance', '%s'%dist)]))  
Example #6
0
    def __init__(self,
                 plot_sheetname,
                 num_chart,
                 parent_obj,
                 excel_colors=True):
        """Inits SpreadSheet with filename and blank content.

        NS: cleans up the namespace callouts of the xml Element

        Attributes::

            plot_sheetname: name of data sheet

        """
        self.i_color = 0  # index into color chart for next curve
        self.i_prim_color = 0  # index into colorL
        self.i_sec_color = 0  # index into color2L

        self.i_symbol_type = 0  # index into SYMBOL_TYPE_LIST

        if excel_colors:
            self.color_list = EXCEL_COLOR_LIST
        else:
            self.color_list = BIG_COLOR_HEXSTR_LIST

        NS = parent_obj.NS

        # Start building new xml Element to be new Sheet in spreadsheet
        attribD = {NS('table:name'): plot_sheetname}
        newsheet = ET.Element(NS('table:table'), attrib=attribD)

        table_shapes = ET.Element(NS('table:shapes'))

        #print( 'table_shapes.text =',table_shapes.text )

        def NS_attrib(attD):
            D = {}
            for key, val in list(attD.items()):
                D[NS(key)] = val
            return D

        attribD = NS_attrib({
            'draw:z-index': "1",
            'draw:id': "id0",
            'draw:style-name': "a0",
            'draw:name': "Chart 1",
            'svg:x': "0in",
            'svg:y': "0in",
            'svg:width': "9.47551in",
            'svg:height': "6.88048in",
            'style:rel-width': "scale",
            'style:rel-height': "scale"
        })
        draw_frame = ET.Element(NS('draw:frame'), attrib=attribD)

        attribD = NS_attrib({
            'xlink:href': "Object %i/" % num_chart,
            'xlink:type': "simple",
            'xlink:show': "embed",
            'xlink:actuate': "onLoad"
        })
        draw_obj = ET.Element(NS('draw:object'), attrib=attribD)

        svg_title = ET.Element(NS('svg:title'))
        svg_desc = ET.Element(NS('svg:desc'))

        draw_frame.append(draw_obj)
        draw_frame.append(svg_title)
        draw_frame.append(svg_desc)
        table_shapes.append(draw_frame)

        tab_col = ET.Element(
            NS('table:table-column'),
            attrib={NS('table:number-columns-repeated'): "16384"})
        tab_row = ET.Element(
            NS('table:table-row'),
            attrib={NS('table:number-rows-repeated'): "1048576"})
        tab_cell = ET.Element(
            NS('table:table-cell'),
            attrib={NS('table:number-columns-repeated'): "16384"})
        tab_row.append(tab_cell)

        newsheet.append(table_shapes)
        newsheet.append(tab_col)
        newsheet.append(tab_row)

        # make sure any added Element objects are in nsOD, rev_nsOD and qnameOD of parent_obj
        def add_tag(tag):
            sL = tag.split('}')
            uri = sL[0][1:]
            name = sL[1]
            parent_obj.qnameOD[tag] = parent_obj.nsOD[uri] + ':' + name

        def add_tags(obj):
            if hasattr(obj, 'tag'):
                add_tag(obj.tag)
            if hasattr(obj, 'attrib'):
                for q, v in list(obj.attrib.items()):
                    add_tag(q)

        for parent in newsheet.iter():
            add_tags(parent)
            for child in parent.getchildren():
                add_tags(child)

        self.xmlSheetObj = newsheet

        self.plot_sheetname = ''
        self.data_sheetname = ''
        self.title = ''
        self.xlabel = ''
        self.ylabel = ''
        self.y2label = ''
        self.ycolL = None
        self.ycol2L = None

        self.logx = False
        self.logy = False
        self.log2y = False

        self.xcolL = []
        self.ycolDataSheetNameL = []

        self.xcol2L = []
        self.ycol2_DataSheetNameL = []

        self.showMarkerL = None
        self.showMarker2L = None
        self.markerTypeL = None
        self.markerType2L = None

        self.showLineL = None
        self.showLine2L = None

        self.lineThkL = None
        self.lineThk2L = None

        self.lineStyleL = None
        self.lineStyle2L = None
        self.set_of_line_styles = set()

        self.markerHtWdL = None
        self.markerHtWd2L = None

        self.showUnits = True

        self.colorL = None
        self.color2L = None

        self.labelL = None
        self.label2L = None
Example #7
0
def build_chart_object_content(chart_obj, plotSheetObj):
    """When chart_obj is input, it still holds values from the original template"""

    chart = chart_obj.find('office:body/office:chart/chart:chart')
    plotSheetObj.chart_obj = chart_obj

    nsOD = chart_obj.rev_nsOD
    doc = plotSheetObj.document

    def set_new_tag(elem, shortname, value):
        """
        Adds shortname to qnames and sets attrib variable on elem
        shortname format is "chart:symbol-type"
        """

        doc.add_tag(NS(shortname, nsOD), plotSheetObj.chart_obj)
        elem.set(NS(shortname, nsOD), value)

    title = chart.find('chart:title/text:p', nsOD)
    #print( 'title.text = ',title.text)
    title.text = plotSheetObj.title

    plot_area = chart.find('chart:plot-area', nsOD)
    #print( 'plot_area =',plot_area )

    axisL = plot_area.findall('chart:axis', nsOD)
    #print( 'axisL =',axisL )
    xaxis = None
    yaxis = None
    x2axis = None
    y2axis = None
    for axis in axisL:
        dim_xy = axis.get(
            '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}dimension')
        dim_name = axis.get(
            '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}name')
        #print( 'dim_xy =',dim_xy )
        if dim_xy == 'x' and dim_name == 'primary-x':
            xaxis = axis
        if dim_xy == 'y' and dim_name == 'primary-y':
            yaxis = axis

        # ODDLY... Excel uses capital X in "secondary-X" label
        #if dim_xy == 'x' and dim_name.startswith('secondary'):
        #    x2axis = axis
        if dim_xy == 'y' and dim_name.startswith('secondary'):
            y2axis = axis

    xtitle = xaxis.find('chart:title/text:p', nsOD)
    ytitle = yaxis.find('chart:title/text:p', nsOD)

    xUnitsStr, yUnitsStr, y2UnitsStr = get_all_units_on_chart(plotSheetObj)

    if plotSheetObj.showUnits:
        xtitle.text = plotSheetObj.xlabel + xUnitsStr
    else:
        xtitle.text = plotSheetObj.xlabel

    if plotSheetObj.showUnits and plotSheetObj.ycolL:
        ytitle.text = plotSheetObj.ylabel + yUnitsStr
    else:
        ytitle.text = plotSheetObj.ylabel

    # Look for secondary y axis
    if plotSheetObj.ycol2L:
        y2title = y2axis.find('chart:title/text:p', nsOD)
        if plotSheetObj.showUnits:
            y2title.text = plotSheetObj.y2label + y2UnitsStr
        else:
            y2title.text = plotSheetObj.y2label

    chart_seriesL = plot_area.findall('chart:series', nsOD)
    y_series = None
    y2_series = None
    for c_series in chart_seriesL:
        axis_name = c_series.get(
            '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}attached-axis')
        if axis_name == 'primary-y':
            y_series = c_series
        if axis_name == 'secondary-y':
            y2_series = c_series
    #print( 'y2_series =',y2_series )

    # =============== Primary Y Axis =========================
    series_label_cell_address = y_series.get(
        '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}label-cell-address')
    #print( 'series_label_cell_address =',series_label_cell_address)

    series_value_cell_range = y_series.get(
        '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}values-cell-range-address'
    )
    #print( 'series_value_cell_range =',series_value_cell_range)
    ycol = plotSheetObj.ycolL[0]
    col_letter = get_col_letters_from_number(ycol)
    sht_name = plotSheetObj.ycolDataSheetNameL[0]
    dataTableObj = doc.data_table_objD[sht_name]
    val_cell_range = '%s.$%s$3:.$%s$%i' % (sht_name, col_letter, col_letter,
                                           dataTableObj.nrows)
    #print( 'val_cell_range =',val_cell_range)

    lab_cell = '%s.$%s$1' % (sht_name, col_letter)
    y_series.set(
        '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}label-cell-address',
        lab_cell)
    y_series.set(
        '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}values-cell-range-address',
        val_cell_range)

    chart_domain = y_series.find('chart:domain', nsOD)
    chart_data_point = y_series.find('chart:data-point', nsOD)
    #print( chart_domain.items())
    #print( chart_data_point.items())

    xcol = plotSheetObj.xcolL[0]
    xcol_letter = get_col_letters_from_number(xcol)
    xval_cell_range = '%s.$%s$3:.$%s$%i' % (sht_name, xcol_letter, xcol_letter,
                                            dataTableObj.nrows)
    chart_domain.set(
        '{urn:oasis:names:tc:opendocument:xmlns:table:1.0}cell-range-address',
        xval_cell_range)

    chart_data_point.set(
        '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}repeated',
        '%i' % (dataTableObj.nrows - 2, ))

    # Look for logarithmic X Axis
    if plotSheetObj.logx:
        auto_styles = chart_obj.find('office:automatic-styles')

        # Find "Axs0"
        logx_style, ipos_logx_style = find_elem_w_attrib(
            'style:style',
            auto_styles,
            nsOD,
            attrib={'style:name': 'Axs0'},
            nth_match=0)
        #print( 'FOUND:  ipos_logx_style = ', ipos_logx_style )

        chart_prop = logx_style.find(NS('style:chart-properties', nsOD))
        chart_prop.attrib = NS_attrib(
            {
                "chart:display-label": "true",
                "chart:link-data-style-to-source": "true",
                "chart:logarithmic": "true",
                "chart:tick-marks-major-inner": "false",
                "chart:tick-marks-major-outer": "true",
                "chart:tick-marks-minor-inner": "true",
                "chart:tick-marks-minor-outer": "true",
                "chart:visible": "true"
            }, nsOD)

        # Find "GMa0"
        logx_style, ipos_logx_style = find_elem_w_attrib(
            'style:style',
            auto_styles,
            nsOD,
            attrib={'style:name': 'GMa0'},
            nth_match=0)
        #print( 'FOUND:  ipos_logx_style = ', ipos_logx_style )
        stroke_style = logx_style.find(NS('style:graphic-properties', nsOD))
        stroke_style.set(NS('draw:stroke', nsOD), 'solid')
        del stroke_style.attrib[NS('draw:stroke-dash', nsOD)]

        # Find "G0S0"
        logx_style, ipos_logx_style = find_elem_w_attrib(
            'style:style',
            auto_styles,
            nsOD,
            attrib={'style:name': 'G0S0'},
            nth_match=0)
        #print( 'FOUND:  ipos_logx_style = ', ipos_logx_style )
        new_elem_1 = ET.SubElement(
            auto_styles,
            "{urn:oasis:names:tc:opendocument:xmlns:style:1.0}style",
            attrib=OrderedDict([
                ('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}family',
                 'chart'),
                ('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name',
                 'GMi0')
            ]))

        new_elem_2 = ET.SubElement(
            new_elem_1,
            "{urn:oasis:names:tc:opendocument:xmlns:style:1.0}graphic-properties",
            attrib=OrderedDict([
                ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}fill',
                 'none'),
                ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}stroke',
                 'dash'),
                ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}stroke-dash',
                 'a4'),
                ('{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-width',
                 '0.01042in'),
                ('{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-color',
                 '#000000'),
                ('{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-opacity',
                 '100%'),
                ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}stroke-linejoin',
                 'round')
            ]))

        # Add minor grid to xaxis
        new_elem_3 = ET.SubElement(
            xaxis,
            "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}grid",
            attrib=OrderedDict([
                ('{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}class',
                 'minor'),
                ('{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}style-name',
                 'GMi0')
            ]))

    if plotSheetObj.ycolL and len(plotSheetObj.ycolL) >= 1:
        auto_styles = chart_obj.find('office:automatic-styles')
        autostyleL = auto_styles.findall('style:style', nsOD)
        ref_series_style = None

        istyle_loc = 0
        for iloc, astyle in enumerate(autostyleL):
            if astyle.get(
                    '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name'
            ) == 'G0S0':
                ref_series_style = astyle
                istyle_loc = iloc + 2

                # graphic-properties
                elem = ref_series_style.find("style:graphic-properties", nsOD)
                c = plotSheetObj.colorL[0]
                if not c is None:
                    elem.set(
                        "{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-color",
                        c)
                    elem.set(
                        "{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}fill-color",
                        c)

                w = plotSheetObj.lineThkL[0]
                if not w is None:
                    elem.set(
                        "{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-width",
                        w)

                if not plotSheetObj.showLineL[0]:
                    #elem.attrib.clear()
                    elem.set(NS("draw:fill", nsOD), "none")
                    elem.set(NS("draw:stroke", nsOD), "none")
                else:
                    # we're showing the line, should it have a style???
                    i_style = plotSheetObj.lineStyleL[0]
                    #print('i_style =', i_style)
                    if i_style > 0:
                        elem.set(NS("draw:stroke-dash", nsOD),
                                 get_dash_a_name(i_style))
                        elem.set(NS("draw:stroke", nsOD), 'dash')
                    else:
                        elem.set(NS("draw:stroke", nsOD), "solid")

                # .............. Failed Experiment ...................
                #doc.add_tag(NS("draw:symbol-color", nsOD), plotSheetObj.chart_obj)
                #elem.set(NS("draw:symbol-color", nsOD), "#999999")
                #doc.add_tag(NS("draw:fill-color", nsOD), plotSheetObj.chart_obj)
                #elem.set(NS("draw:fill-color", nsOD), "#999999")
                #elem.set(NS("draw:fill", nsOD), "solid")

                # chart-properties
                elem = ref_series_style.find("style:chart-properties", nsOD)
                if plotSheetObj.showMarkerL[
                        0]:  # showMarkerL is guaranteed to have same dimension as ycolL
                    elem.set(
                        "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}symbol-type",
                        "automatic")
                else:
                    elem.set(
                        "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}symbol-type",
                        "none")
                    for at in [
                            NS("chart:symbol-name", nsOD),
                            NS("chart:symbol-width", nsOD),
                            NS("chart:symbol-height", nsOD)
                    ]:
                        if elem.get(at, None) is not None:
                            del elem.attrib[at]

                # elem is  chart-properties
                if not plotSheetObj.showLineL[0]:
                    set_new_tag(elem, "chart:symbol-type", "named-symbol")
                    set_new_tag(elem, "chart:symbol-name",
                                plotSheetObj.markerTypeL[0])
                    hw = plotSheetObj.markerHtWdL[0]
                    set_new_tag(elem, "chart:symbol-width", hw)
                    set_new_tag(elem, "chart:symbol-height", hw)

        # Look for logarithmic scale on primary y
        if plotSheetObj.logy:
            #print( 'Got log y' )

            # Find "Axs1"
            logy_style, ipos_logy_style = find_elem_w_attrib(
                'style:style',
                auto_styles,
                nsOD,
                attrib={'style:name': 'Axs1'},
                nth_match=0)
            #print( 'FOUND:  ipos_logy_style = ', ipos_logy_style )
            chart_prop = logy_style.find(NS('style:chart-properties', nsOD))

            chart_prop.set(NS("chart:logarithmic", nsOD), "true")
            chart_prop.set(NS("chart:tick-marks-minor-inner", nsOD), "true")
            chart_prop.set(NS("chart:tick-marks-minor-outer", nsOD), "true")

            # Find "GMa1"
            logy_style, ipos_logy_style = find_elem_w_attrib(
                'style:style',
                auto_styles,
                nsOD,
                attrib={'style:name': 'GMa1'},
                nth_match=0)
            #print( 'FOUND:  ipos_logy_style = ', ipos_logy_style )
            logy_style.set(NS("draw:stroke", nsOD), "dash")

            # Find "G0S1"
            logy_style, ipos_logy_style = find_elem_w_attrib(
                'style:style',
                auto_styles,
                nsOD,
                attrib={'style:name': 'G0S1'},
                nth_match=0)
            #print( 'FOUND:  ipos_logy_style = ', ipos_logy_style )

            new_elem_1 = ET.SubElement(
                auto_styles,
                "{urn:oasis:names:tc:opendocument:xmlns:style:1.0}style",
                attrib=OrderedDict([
                    ('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}family',
                     'chart'),
                    ('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name',
                     'GMi1')
                ]))

            new_elem_2 = ET.SubElement(
                new_elem_1,
                "{urn:oasis:names:tc:opendocument:xmlns:style:1.0}graphic-properties",
                attrib=OrderedDict([
                    ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}fill',
                     'none'),
                    ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}stroke',
                     'dash'),
                    ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}stroke-dash',
                     'a4'),
                    ('{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-width',
                     '0.01042in'),
                    ('{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-color',
                     '#000000'),
                    ('{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-opacity',
                     '100%'),
                    ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}stroke-linejoin',
                     'round')
                ]))

            # Add minor grid to yaxis
            new_elem_3 = ET.SubElement(
                yaxis,
                "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}grid",
                attrib=OrderedDict([
                    ('{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}class',
                     'minor'),
                    ('{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}style-name',
                     'GMi1')
                ]))

        #print( ref_series_style.items())

        nG0S = 1
        for ycol in plotSheetObj.ycolL[1:]:
            new_style = deepcopy(ref_series_style)
            new_style.set(
                '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name',
                'G0S%i' % nG0S)

            elem = new_style.find("style:graphic-properties", nsOD)
            c = plotSheetObj.colorL[nG0S]
            if not c is None:
                elem.set(
                    "{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-color",
                    c)
                elem.set(
                    "{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}fill-color",
                    c)

            w = plotSheetObj.lineThkL[nG0S]
            if not w is None:
                elem.set(
                    "{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-width",
                    w)

            if not plotSheetObj.showLineL[nG0S]:
                #elem.attrib.clear()
                elem.set(NS("draw:fill", nsOD), "none")
                elem.set(NS("draw:stroke", nsOD), "none")
            else:
                i_style = plotSheetObj.lineStyleL[nG0S]
                #print('i_style =', i_style)
                if i_style > 0:
                    elem.set(NS("draw:stroke-dash", nsOD),
                             get_dash_a_name(i_style))
                    elem.set(NS("draw:stroke", nsOD), 'dash')
                else:
                    elem.set(NS("draw:stroke", nsOD), "solid")

            elem = new_style.find("style:chart-properties", nsOD)
            if plotSheetObj.showMarkerL[
                    nG0S]:  # showMarkerL is guaranteed to have same dimension as ycolL
                elem.set(
                    "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}symbol-type",
                    "automatic")
            else:
                elem.set(
                    "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}symbol-type",
                    "none")
                for at in [
                        NS("chart:symbol-name", nsOD),
                        NS("chart:symbol-width", nsOD),
                        NS("chart:symbol-height", nsOD)
                ]:
                    if elem.get(at, None) is not None:
                        del elem.attrib[at]

            # elem is  chart-properties
            if not plotSheetObj.showLineL[nG0S]:
                set_new_tag(elem, "chart:symbol-type", "named-symbol")
                set_new_tag(elem, "chart:symbol-name",
                            plotSheetObj.markerTypeL[nG0S])
                hw = plotSheetObj.markerHtWdL[nG0S]
                set_new_tag(elem, "chart:symbol-width", hw)
                set_new_tag(elem, "chart:symbol-height", hw)

            auto_styles.insert(istyle_loc, new_style)
            istyle_loc += 1

            new_chart_series = deepcopy(y_series)
            new_chart_series.set(
                '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}style-name',
                'G0S%i' % nG0S)

            col_letter = get_col_letters_from_number(ycol)
            sht_name = plotSheetObj.ycolDataSheetNameL[nG0S]
            dataTableObj = doc.data_table_objD[sht_name]
            val_cell_range = '%s.$%s$3:.$%s$%i' % (
                sht_name, col_letter, col_letter, dataTableObj.nrows)
            #print( 'val_cell_range =',val_cell_range)

            lab_cell = '%s.$%s$1' % (sht_name, col_letter)
            new_chart_series.set(
                '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}label-cell-address',
                lab_cell)
            new_chart_series.set(
                '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}values-cell-range-address',
                val_cell_range)

            xcol = plotSheetObj.xcolL[nG0S]
            xcol_letter = get_col_letters_from_number(xcol)
            xval_cell_range = '%s.$%s$3:.$%s$%i' % (
                sht_name, xcol_letter, xcol_letter, dataTableObj.nrows)
            new_chart_series.set(
                '{urn:oasis:names:tc:opendocument:xmlns:table:1.0}cell-range-address',
                xval_cell_range)

            #ipos = len(plot_area)-1
            #plot_area.insert(ipos, new_chart_series )
            insert_below_series_named('G0S%i' % (nG0S - 1, ), new_chart_series,
                                      plot_area)

            nG0S += 1

    # =============== Secondary Y Axis =========================
    # Look for secondary y axis
    if (plotSheetObj.ycol2L is not None) and (len(plotSheetObj.ycol2L) > 0):
        series_label_cell_address = y2_series.get(
            '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}label-cell-address'
        )
        #print( 'Y2 series_label_cell_address =',series_label_cell_address)

        series_value_cell_range = y2_series.get(
            '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}values-cell-range-address'
        )
        #print( 'Y2 series_value_cell_range =',series_value_cell_range)
        ycol = plotSheetObj.ycol2L[0]
        col_letter = get_col_letters_from_number(ycol)
        sht_name = plotSheetObj.ycol2_DataSheetNameL[0]
        dataTableObj = doc.data_table_objD[sht_name]
        val_cell_range = '%s.$%s$3:.$%s$%i' % (sht_name, col_letter,
                                               col_letter, dataTableObj.nrows)
        #print( 'Y2 val_cell_range =',val_cell_range)

        lab_cell = '%s.$%s$1' % (sht_name, col_letter)
        y2_series.set(
            '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}label-cell-address',
            lab_cell)
        y2_series.set(
            '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}values-cell-range-address',
            val_cell_range)

        chart_domain = y2_series.find('chart:domain', nsOD)
        chart_data_point = y2_series.find('chart:data-point', nsOD)
        #print( chart_domain.items())
        #print( chart_data_point.items())

        xcol = plotSheetObj.xcol2L[0]
        xcol_letter = get_col_letters_from_number(xcol)
        xval_cell_range = '%s.$%s$3:.$%s$%i' % (
            sht_name, xcol_letter, xcol_letter, dataTableObj.nrows)
        chart_domain.set(
            '{urn:oasis:names:tc:opendocument:xmlns:table:1.0}cell-range-address',
            xval_cell_range)

        chart_data_point.set(
            '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}repeated',
            '%i' % (dataTableObj.nrows - 2, ))

        # Look for logarithmic scale on primary y
        if plotSheetObj.log2y:
            #print( 'Got log on secondary y' )

            # Find "Axs2"
            logy_style, ipos_logy_style = find_elem_w_attrib(
                'style:style',
                auto_styles,
                nsOD,
                attrib={'style:name': 'Axs2'},
                nth_match=0)
            #print( 'FOUND:  ipos_logy_style = ', ipos_logy_style )
            chart_prop = logy_style.find(NS('style:chart-properties', nsOD))

            chart_prop.set(NS("chart:logarithmic", nsOD), "true")
            chart_prop.set(NS("chart:tick-marks-minor-inner", nsOD), "true")
            chart_prop.set(NS("chart:tick-marks-minor-outer", nsOD), "true")

            # Make "GMi2"
            new_elem_1 = ET.SubElement(
                auto_styles,
                "{urn:oasis:names:tc:opendocument:xmlns:style:1.0}style",
                attrib=OrderedDict([
                    ('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}family',
                     'chart'),
                    ('{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name',
                     'GMi2')
                ]))

            # Looks better with only one set of y grids... Seems obvious now
            if 0:  #plotSheetObj.ycolL and (not plotSheetObj.logy):
                new_elem_2 = ET.SubElement(
                    new_elem_1,
                    "{urn:oasis:names:tc:opendocument:xmlns:style:1.0}graphic-properties",
                    attrib=OrderedDict([
                        ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}fill',
                         'none'),
                        ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}stroke',
                         'dash'),
                        ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}stroke-dash',
                         'a4'),
                        ('{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-width',
                         '0.01042in'),
                        ('{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-color',
                         '#000000'),
                        ('{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-opacity',
                         '100%'),
                        ('{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}stroke-linejoin',
                         'round')
                    ]))

                # Add minor grid to yaxis
                new_elem_3 = ET.SubElement(
                    y2axis,
                    "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}grid",
                    attrib=OrderedDict([
                        ('{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}class',
                         'minor'),
                        ('{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}style-name',
                         'GMi2')
                    ]))

        #  If more than one curve on secondary y...
        if len(plotSheetObj.ycol2L) >= 1:
            auto_styles = chart_obj.find('office:automatic-styles')
            autostyleL = auto_styles.findall('style:style', nsOD)
            ref_series_style = None

            istyle_loc = 0
            for iloc, astyle in enumerate(autostyleL):
                if astyle.get(
                        '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name'
                ) == 'G1S0':
                    ref_series_style = astyle
                    istyle_loc = iloc + 2

                    elem = ref_series_style.find("style:graphic-properties",
                                                 nsOD)
                    c = plotSheetObj.color2L[0]
                    if not c is None:
                        elem.set(
                            "{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-color",
                            c)
                        elem.set(
                            "{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}fill-color",
                            c)

                    w = plotSheetObj.lineThk2L[0]
                    if not w is None:
                        elem.set(
                            "{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-width",
                            w)

                    if not plotSheetObj.showLine2L[0]:
                        elem.set(NS("draw:fill", nsOD), "none")
                        elem.set(NS("draw:stroke", nsOD), "none")
                    else:

                        i_style = plotSheetObj.lineStyle2L[0]
                        #print('i_style =', i_style)
                        if i_style > 0:
                            elem.set(NS("draw:stroke-dash", nsOD),
                                     get_dash_a_name(i_style))
                            elem.set(NS("draw:stroke", nsOD), 'dash')
                        else:
                            elem.set(NS("draw:stroke", nsOD), "solid")

                    elem = ref_series_style.find("style:chart-properties",
                                                 nsOD)
                    if plotSheetObj.showMarkerL[
                            0]:  # showMarkerL is guaranteed to have same dimension as ycol2L
                        elem.set(
                            "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}symbol-type",
                            "automatic")
                    else:
                        elem.set(
                            "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}symbol-type",
                            "none")
                        for at in [
                                NS("chart:symbol-name", nsOD),
                                NS("chart:symbol-width", nsOD),
                                NS("chart:symbol-height", nsOD)
                        ]:
                            if elem.get(at, None) is not None:
                                del elem.attrib[at]

                    # elem is  chart-properties
                    if not plotSheetObj.showLine2L[0]:
                        set_new_tag(elem, "chart:symbol-type", "named-symbol")
                        set_new_tag(elem, "chart:symbol-name",
                                    plotSheetObj.markerType2L[0])
                        hw = plotSheetObj.markerHtWd2L[0]
                        set_new_tag(elem, "chart:symbol-width", hw)
                        set_new_tag(elem, "chart:symbol-height", hw)

            plotSheetObj.ref_series_style2 = ref_series_style

            #print( ref_series_style.items())

            nG1S = 1
            for ycol in plotSheetObj.ycol2L[1:]:
                new_style = deepcopy(ref_series_style)
                new_style.set(
                    '{urn:oasis:names:tc:opendocument:xmlns:style:1.0}name',
                    'G1S%i' % nG1S)

                elem = new_style.find("style:graphic-properties", nsOD)
                c = plotSheetObj.color2L[nG1S]
                if not c is None:
                    elem.set(
                        "{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-color",
                        c)
                    elem.set(
                        "{urn:oasis:names:tc:opendocument:xmlns:drawing:1.0}fill-color",
                        c)

                w = plotSheetObj.lineThk2L[nG1S]
                if not w is None:
                    elem.set(
                        "{urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0}stroke-width",
                        w)

                if not plotSheetObj.showLine2L[nG1S]:
                    elem.set(NS("draw:fill", nsOD), "none")
                    elem.set(NS("draw:stroke", nsOD), "none")
                else:
                    i_style = plotSheetObj.lineStyle2L[nG1S]
                    #print('i_style =', i_style)
                    if i_style > 0:
                        elem.set(NS("draw:stroke-dash", nsOD),
                                 get_dash_a_name(i_style))
                        elem.set(NS("draw:stroke", nsOD), 'dash')
                    else:
                        elem.set(NS("draw:stroke", nsOD), "solid")

                elem = new_style.find("style:chart-properties", nsOD)
                if plotSheetObj.showMarker2L[
                        nG1S]:  # showMarkerL is guaranteed to have same dimension as ycol2L
                    elem.set(
                        "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}symbol-type",
                        "automatic")
                else:
                    elem.set(
                        "{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}symbol-type",
                        "none")
                    for at in [
                            NS("chart:symbol-name", nsOD),
                            NS("chart:symbol-width", nsOD),
                            NS("chart:symbol-height", nsOD)
                    ]:
                        if elem.get(at, None) is not None:
                            del elem.attrib[at]

                # elem is  chart-properties
                if not plotSheetObj.showLine2L[nG1S]:
                    set_new_tag(elem, "chart:symbol-type", "named-symbol")
                    set_new_tag(elem, "chart:symbol-name",
                                plotSheetObj.markerType2L[nG1S])
                    hw = plotSheetObj.markerHtWd2L[nG1S]
                    set_new_tag(elem, "chart:symbol-width", hw)
                    set_new_tag(elem, "chart:symbol-height", hw)

                auto_styles.insert(istyle_loc, new_style)
                istyle_loc += 1

                new_chart_series = deepcopy(y2_series)
                new_chart_series.set(
                    '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}style-name',
                    'G1S%i' % nG1S)

                col_letter = get_col_letters_from_number(ycol)
                sht_name = plotSheetObj.ycol2_DataSheetNameL[nG1S]
                dataTableObj = doc.data_table_objD[sht_name]
                val_cell_range = '%s.$%s$3:.$%s$%i' % (
                    sht_name, col_letter, col_letter, dataTableObj.nrows)
                #print( 'val_cell_range =',val_cell_range)

                lab_cell = '%s.$%s$1' % (sht_name, col_letter)
                new_chart_series.set(
                    '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}label-cell-address',
                    lab_cell)
                new_chart_series.set(
                    '{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}values-cell-range-address',
                    val_cell_range)

                xcol = plotSheetObj.xcol2L[nG1S]
                xcol_letter = get_col_letters_from_number(xcol)
                xval_cell_range = '%s.$%s$3:.$%s$%i' % (
                    sht_name, xcol_letter, xcol_letter, dataTableObj.nrows)
                new_chart_series.set(
                    '{urn:oasis:names:tc:opendocument:xmlns:table:1.0}cell-range-address',
                    xval_cell_range)

                ipos = len(plot_area) - 1
                plot_area.insert(ipos, new_chart_series)

                nG1S += 1

    #plot_area._children.sort(  key=lambda child: child.get('{urn:oasis:names:tc:opendocument:xmlns:chart:1.0}style-name', '0') )

    plotSheetObj.istyle_loc = istyle_loc
    plotSheetObj.y_series = y_series
    plotSheetObj.chart_obj = chart_obj
Example #8
0
    def __init__(self, xml_file_name_or_src):
        """
        Read and parse xml file using modified version of standard python
        xml.etree.ElementTree.

        xml_file_name_or_src can be a file name like: "content.xml" OR
        can be xml source.
        """
        #xml_file_name_or_src = xml_file_name_or_src.decode('utf-8')
        
        if xml_file_name_or_src.endswith('.xml') and len(xml_file_name_or_src)<256:
            self.xml_file_name_or_src = xml_file_name_or_src

            fInp = io.open(xml_file_name_or_src, 'rt', encoding='utf-8')
            xml_src = fInp.read()
            fInp.close()
        else:
            self.xml_file_name_or_src = None
            xml_src = xml_file_name_or_src

        self.xml_header = '' # Assume no header unless found at head of file
        match = header_re.match(xml_src)
        if match:
            #print( 'Found XML Header: ' + match.group(0) )
            self.xml_header = match.group(0) # will need \n when serialized

        # ns entries like: ('urn:oasis:names:tc:opendocument:xmlns:table:1.0', u'table')
        self.nsOD = OrderedDict()

        # rev_ns entries like: (u'table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0')
        self.rev_nsOD = OrderedDict()

        # qname entries like: ('{urn:oasis:names:tc:opendocument:xmlns:office:1.0}document-content', u'office:document-content')
        self.qnameOD = OrderedDict()

        events = ("start", "end", "start-ns", "end-ns")
        context = ET.iterparse(StringIO(xml_src), events=events)

        for event, elem in context:
            if event=="start":
                #print('type elem.tag =', type(elem.tag))
                #print('     type("}") =',type("}"))
                sL = elem.tag.split('}')
                if len(sL) == 2:
                    name = sL[1]
                    uri = sL[0][1:]
                    self.qnameOD[elem.tag] = '%s:%s'%(self.nsOD[uri], name)

                for qname,v in elem.attrib.items():
                    sL = qname.split('}')
                    if len(sL) == 2:
                        name = sL[1]
                        uri = sL[0][1:]
                        self.qnameOD[qname] = '%s:%s'%(self.nsOD[uri], name)
            if event=="start-ns":
                self.nsOD[elem[1]] = elem[0]     # like: ('urn:oasis:names:tc:opendocument:xmlns:table:1.0', u'table')
                self.rev_nsOD[elem[0]] = elem[1] # like: (u'table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0')

        self.context = context
        #self.root = ET.ElementTree( context.root )
        self.root = context.root

        self.parentD = {} # index=child Element object, value=parent Element object
        self.depthD = {}  # index=Element object, value = depth in xml tree
        self.original_posD = {}  # index=Element object, value=tuple of child position (e.g. (0,3,1))
        self.get_elem_from_orig_posD = {}  # reverse lookup of "original_posD"
        
        self.max_depth = 0
        self.short_pathD = {} # index=Element, value = short name (like: "ns0:name1/ns1:xyz/ns3:abc")
        # After building tree, create self.parentD for all Elements
        self.parentD[self.root] = None
        self.depthD[self.root] = 0
        self.short_pathD[self.root] = self.qnameOD[ self.root.tag ] # no calc req'd... just = qname
        
        self.original_posD[self.root] = (0,) # tuple of position

        temp_short_path_counterD = {} # just used here to help count occurances of short path
        self.short_path_counterD = {} # index=Element, value=short path counter value
        self.short_path_parent_counterD = {} #  index=Element, value=parent's short path counter value
        self.short_path_counterD[self.root] = 1 # 1st (and only) occurance
        self.short_path_parent_counterD[self.root] = 1 # 1st (and only) occurance

        for parent in self.root.iter():
            try:
                for ichild, child in enumerate(parent.getchildren()):
                    self.parentD[child] = parent
                    self.depthD[child] = self.depthD[parent] + 1
                    self.max_depth = max(self.max_depth, self.depthD[child])
                    
                    L = list(self.original_posD[parent])
                    L.append( ichild )
                    self.original_posD[child] = tuple( L )

                    short_path = self.get_short_path( child )
                    self.short_pathD[child] = short_path

                    temp_short_path_counterD[(parent,short_path)] = temp_short_path_counterD.get((parent,short_path), 0) + 1
                    self.short_path_counterD[child] = '%s,%s'%(self.short_path_counterD[parent],
                                                       temp_short_path_counterD[(parent,short_path)])
                    self.short_path_parent_counterD[child] = '%s'%self.short_path_counterD[parent]

            except:
                print( 'NOTICE: No children for:', parent )
                
        for key,item in self.original_posD.items():
            self.get_elem_from_orig_posD[item] = key # get elem from original_posD
Example #9
0
    def __init__(self, data_sheetname, list_of_rows, parent_obj):
        """Inits SpreadSheet with filename and blank content.

        NS: cleans up the namespace callouts of the xml Element

        Attributes::

            data_sheetname: name of data sheet
            nrows: number of rows including label and units rows
            ncols: max number of cols
            labelL: list of labels
            unitsL: list of units

        """

        NS = parent_obj.NS

        self.data_sheetname = data_sheetname
        self.list_of_rows = list_of_rows

        # calc number of rows and columns in data
        self.nrows = len(list_of_rows)
        self.ncols = 0
        for row in list_of_rows:
            self.ncols = max(self.ncols, len(row))

        # make sure that row1 and row2 contain labels and units
        self.labelL = []
        self.unitsL = []
        for n in range(self.ncols):
            try:
                s = str(list_of_rows[0][n]).strip()
            except:
                s = 'Column %i' % (n + 1, )
            self.labelL.append(s)

            try:
                s = str(list_of_rows[1][n]).strip()
            except:
                s = ''
            self.unitsL.append(s)

        # Start building new xml Element to be new Sheet in spreadsheet
        #print( nsmap )
        attribD = {
            NS('table:name'): data_sheetname,
            NS('table:style-name'): "ta1"
        }
        newsheet = ET.Element(NS('table:table'), attrib=attribD)

        colD = {
            NS('table:style-name'): "co1",
            NS('table:number-columns-repeated'): "16384",
            NS('table:default-cell-style-name'): "ce1"
        }
        col_elm = ET.Element(NS('table:table-column'), attrib=colD)
        newsheet.append(col_elm)

        str_cellD = {
            NS('office:value-type'): "string",
            NS('table:style-name'): "ce1"
        }
        float_cellD = {
            NS('office:value-type'): "float",
            NS('table:style-name'): "ce1"
        }

        row_rep = 1048576  # max number of rows

        for row in list_of_rows:
            row_obj = ET.Element(NS('table:table-row'),
                                 attrib={NS('table:style-name'): "ro1"})

            col_rep = 16384  # max number of columns

            for value in row:
                try:
                    fval = float(value)
                    float_cellD[NS('office:value')] = str(fval)
                    D = float_cellD
                    text_p = "%g" % fval
                except:
                    D = str_cellD
                    text_p = "%s" % value

                cell_obj = ET.Element(NS('table:table-cell'), attrib=D)
                text_obj = ET.Element(NS('text:p'))
                text_obj.text = text_p
                cell_obj.append(text_obj)
                row_obj.append(cell_obj)
                col_rep -= 1  # decrement max available columns remaining

            last_cell_obj = ET.Element(
                NS('table:table-cell'),
                attrib={NS('table:number-columns-repeated'): "%i" % col_rep})
            row_obj.append(last_cell_obj)
            newsheet.append(row_obj)
            row_rep -= 1  # decrement max remaining number of rows

        last_row_obj = ET.Element(NS('table:table-row'),
                                  attrib={
                                      NS('table:style-name'):
                                      "ro1",
                                      NS('table:number-rows-repeated'):
                                      "%i" % row_rep
                                  })
        last_row_obj.append(
            ET.Element(NS('table:table-cell'),
                       attrib={NS('table:number-columns-repeated'): "16384"}))

        newsheet.append(last_row_obj)

        # make sure any added Element objects are in nsOD, rev_nsOD and qnameOD of parent_obj

        # make sure any added Element objects are in nsOD, rev_nsOD and qnameOD of parent_obj
        def add_tag(tag):
            sL = tag.split('}')
            uri = sL[0][1:]
            name = sL[1]
            parent_obj.qnameOD[tag] = parent_obj.nsOD[uri] + ':' + name

        def add_tags(obj):
            if hasattr(obj, 'tag'):
                add_tag(obj.tag)
            if hasattr(obj, 'attrib'):
                for q, v in list(obj.attrib.items()):
                    add_tag(q)

        for parent in newsheet.iter():
            add_tags(parent)
            for child in parent.getchildren():
                add_tags(child)

        self.xmlSheetObj = newsheet
Example #10
0
    def __init__(self, xml_file_name_or_src):
        """
        Read and parse xml file using modified version of standard python
        xml.etree.ElementTree.

        xml_file_name_or_src can be a file name like: "content.xml" OR
        can be xml source.
        """
        #xml_file_name_or_src = xml_file_name_or_src.decode('utf-8')

        if xml_file_name_or_src.endswith(
                '.xml') and len(xml_file_name_or_src) < 256:
            self.xml_file_name_or_src = xml_file_name_or_src

            fInp = io.open(xml_file_name_or_src, 'rt', encoding='utf-8')
            xml_src = fInp.read()
            fInp.close()
        else:
            self.xml_file_name_or_src = None
            xml_src = xml_file_name_or_src

        self.xml_header = ''  # Assume no header unless found at head of file
        match = header_re.match(xml_src)
        if match:
            #print( 'Found XML Header: ' + match.group(0) )
            self.xml_header = match.group(0)  # will need \n when serialized

        # ns entries like: ('urn:oasis:names:tc:opendocument:xmlns:table:1.0', u'table')
        self.nsOD = OrderedDict()

        # rev_ns entries like: (u'table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0')
        self.rev_nsOD = OrderedDict()

        # qname entries like: ('{urn:oasis:names:tc:opendocument:xmlns:office:1.0}document-content', u'office:document-content')
        self.qnameOD = OrderedDict()

        events = ("start", "end", "start-ns", "end-ns")
        context = ET.iterparse(StringIO(xml_src), events=events)

        for event, elem in context:
            if event == "start":
                #print('type elem.tag =', type(elem.tag))
                #print('     type("}") =',type("}"))
                sL = elem.tag.split('}')
                if len(sL) == 2:
                    name = sL[1]
                    uri = sL[0][1:]
                    self.qnameOD[elem.tag] = '%s:%s' % (self.nsOD[uri], name)

                for qname, v in list(elem.attrib.items()):
                    sL = qname.split('}')
                    if len(sL) == 2:
                        name = sL[1]
                        uri = sL[0][1:]
                        self.qnameOD[qname] = '%s:%s' % (self.nsOD[uri], name)
            if event == "start-ns":
                self.nsOD[elem[1]] = elem[
                    0]  # like: ('urn:oasis:names:tc:opendocument:xmlns:table:1.0', u'table')
                self.rev_nsOD[elem[0]] = elem[
                    1]  # like: (u'table', 'urn:oasis:names:tc:opendocument:xmlns:table:1.0')

        self.context = context
        #self.root = ET.ElementTree( context.root )
        self.root = context.root

        self.parentD = {
        }  # index=child Element object, value=parent Element object
        self.depthD = {}  # index=Element object, value = depth in xml tree
        self.original_posD = {
        }  # index=Element object, value=tuple of child position (e.g. (0,3,1))
        self.get_elem_from_orig_posD = {}  # reverse lookup of "original_posD"

        self.max_depth = 0
        self.short_pathD = {
        }  # index=Element, value = short name (like: "ns0:name1/ns1:xyz/ns3:abc")
        # After building tree, create self.parentD for all Elements
        self.parentD[self.root] = None
        self.depthD[self.root] = 0
        self.short_pathD[self.root] = self.qnameOD[
            self.root.tag]  # no calc req'd... just = qname

        self.original_posD[self.root] = (0, )  # tuple of position

        temp_short_path_counterD = {
        }  # just used here to help count occurances of short path
        self.short_path_counterD = {
        }  # index=Element, value=short path counter value
        self.short_path_parent_counterD = {
        }  #  index=Element, value=parent's short path counter value
        self.short_path_counterD[self.root] = 1  # 1st (and only) occurance
        self.short_path_parent_counterD[
            self.root] = 1  # 1st (and only) occurance

        for parent in self.root.iter():
            try:
                for ichild, child in enumerate(parent.getchildren()):
                    self.parentD[child] = parent
                    self.depthD[child] = self.depthD[parent] + 1
                    self.max_depth = max(self.max_depth, self.depthD[child])

                    L = list(self.original_posD[parent])
                    L.append(ichild)
                    self.original_posD[child] = tuple(L)

                    short_path = self.get_short_path(child)
                    self.short_pathD[child] = short_path

                    temp_short_path_counterD[(
                        parent, short_path)] = temp_short_path_counterD.get(
                            (parent, short_path), 0) + 1
                    self.short_path_counterD[child] = '%s,%s' % (
                        self.short_path_counterD[parent],
                        temp_short_path_counterD[(parent, short_path)])
                    self.short_path_parent_counterD[
                        child] = '%s' % self.short_path_counterD[parent]

            except:
                print('NOTICE: No children for:', parent)

        for key, item in list(self.original_posD.items()):
            self.get_elem_from_orig_posD[
                item] = key  # get elem from original_posD