o
    ;Di9=                     @   s  d dl mZmZmZ zd dlmZ W n ey$   d dlm  mZ Y nw d dl	m
Z
 d dlZd dlmZmZ d dlmZmZmZ d dlmZ d dlmZ d	d
 ZG dd deZdd Zdd Zdd Z			d#ddZdd Zdd Zdd Zdd Z dd  Z!d!d" Z"dS )$    )absolute_importprint_functiondivision)etreeN)
attrgetter)string_types	text_type)Table
fieldnamesiterpeek)read_source_from_arg)totextc                 O   s   t | } t| g|R i |S )a  
    Extract data from an XML file. E.g.::

        >>> import petl as etl
        >>> # setup a file to demonstrate with
        ... d = '''<table>
        ...     <tr>
        ...         <td>foo</td><td>bar</td>
        ...     </tr>
        ...     <tr>
        ...         <td>a</td><td>1</td>
        ...     </tr>
        ...     <tr>
        ...         <td>b</td><td>2</td>
        ...     </tr>
        ...     <tr>
        ...         <td>c</td><td>2</td>
        ...     </tr>
        ... </table>'''
        >>> with open('example.file1.xml', 'w') as f:
        ...     f.write(d)
        ...
        212
        >>> table1 = etl.fromxml('example.file1.xml', 'tr', 'td')
        >>> table1
        +-----+-----+
        | foo | bar |
        +=====+=====+
        | 'a' | '1' |
        +-----+-----+
        | 'b' | '2' |
        +-----+-----+
        | 'c' | '2' |
        +-----+-----+


    If the data values are stored in an attribute, provide the attribute
    name as an extra positional argument::

        >>> d = '''<table>
        ...     <tr>
        ...         <td v='foo'/><td v='bar'/>
        ...     </tr>
        ...     <tr>
        ...         <td v='a'/><td v='1'/>
        ...     </tr>
        ...     <tr>
        ...         <td v='b'/><td v='2'/>
        ...     </tr>
        ...     <tr>
        ...         <td v='c'/><td v='2'/>
        ...     </tr>
        ... </table>'''
        >>> with open('example.file2.xml', 'w') as f:
        ...     f.write(d)
        ...
        220
        >>> table2 = etl.fromxml('example.file2.xml', 'tr', 'td', 'v')
        >>> table2
        +-----+-----+
        | foo | bar |
        +=====+=====+
        | 'a' | '1' |
        +-----+-----+
        | 'b' | '2' |
        +-----+-----+
        | 'c' | '2' |
        +-----+-----+

    Data values can also be extracted by providing a mapping of field
    names to element paths::

        >>> d = '''<table>
        ...     <row>
        ...         <foo>a</foo><baz><bar v='1'/><bar v='3'/></baz>
        ...     </row>
        ...     <row>
        ...         <foo>b</foo><baz><bar v='2'/></baz>
        ...     </row>
        ...     <row>
        ...         <foo>c</foo><baz><bar v='2'/></baz>
        ...     </row>
        ... </table>'''
        >>> with open('example.file3.xml', 'w') as f:
        ...     f.write(d)
        ...
        223
        >>> table3 = etl.fromxml('example.file3.xml', 'row',
        ...                      {'foo': 'foo', 'bar': ('baz/bar', 'v')})
        >>> table3
        +------------+-----+
        | bar        | foo |
        +============+=====+
        | ('1', '3') | 'a' |
        +------------+-----+
        | '2'        | 'b' |
        +------------+-----+
        | '2'        | 'c' |
        +------------+-----+

    If `lxml <http://lxml.de/>`_ is installed, full XPath expressions can be
    used.

    Note that the implementation is currently **not** streaming, i.e.,
    the whole document is loaded into memory.

    If multiple elements match a given field, all values are reported as a
    tuple.

    If there is more than one element name used for row values, a tuple
    or list of paths can be provided, e.g.,
    ``fromxml('example.file.html', './/tr', ('th', 'td'))``.

    Optionally a custom parser can be provided, e.g.::

        >>> from lxml import etree # doctest: +SKIP
        ... my_parser = etree.XMLParser(resolve_entities=False) # doctest: +SKIP
        ... table4 = etl.fromxml('example.file1.xml', 'tr', 'td', parser=my_parser) # doctest: +SKIP

    )r   XmlView)sourceargskwargs r   D/var/www/Datamplify/venv/lib/python3.10/site-packages/petl/io/xml.pyfromxml   s   zr   c                   @   s   e Zd Zdd Zdd ZdS )r   c                 O   s   || _ || _t|dkr't|d tttfr'|d | _|d | _d | _	d | _
n;t|dkrEt|d trE|d | _d | _|d | _	d | _
nt|dkr^|d | _|d | _d | _	|d | _
nJ d|dd | _|dd | _d S )	N      r      Fzbad parametersmissingparser)r   r   len
isinstancer   tuplelistrmatchvmatchvdictattrdictgetr   user_parser)selfr   r   r   r   r   r   __init__   s(    





zXmlView.__init__c           
      #   s   j }j}jd}tj}tj||d}t|ds#|j	|_
|d urd|
jD ]5jd u r9td nfdd t|trJ	|}ntjfdd|D  }t fd	d
|D V  q-nXtttt| }|V  t t |D ]*}j| }t|tr||< tj|< qz|d |< |d }	t|	j|< qz|
jD ]tfdd
|D V  qW d    d S W d    d S 1 sw   Y  d S )Nrb)r   iterfindtextc                    s   |   jS N)r#   r!   )e)r%   r   r   <lambda>   s    z"XmlView.__iter__.<locals>.<lambda>c                       g | ]}  |qS r   findall).0enm)rowelmr   r   
<listcomp>   s    z$XmlView.__iter__.<locals>.<listcomp>c                 3   s    | ]} |V  qd S r*   r   )r0   velm)getvr   r   	<genexpr>   s    z#XmlView.__iter__.<locals>.<genexpr>r   r   c                 3   s&    | ]}|   | V  qd S r*   r.   )r0   f)r2   vgettersvmatchesr   r   r6      s    )r   r    r   open_create_xml_parserr$   r   parsehasattrr/   r(   r   r!   r   r   r   	itertoolschainr   sortedmapr   keysr"   element_text_getterr   attribute_text_getter)
r%   r   r    xmlfparser2treevelmsfldsr7   r!   r   )r5   r2   r%   r8   r9   r   __iter__   sT   






/"zXmlView.__iter__N)__name__
__module____qualname__r&   rJ   r   r   r   r   r      s    r   c                 C   s0   | d ur| S zt jddW S  ty   Y d S w )NF)resolve_entities)r   	XMLParser	TypeError)r$   r   r   r   r;      s   r;   c                    s    fdd}|S )Nc                    s8   t | dkrtdd | D S t | dkr| d jS  S )Nr   c                 s   s    | ]}|j V  qd S r*   )r)   r0   r+   r   r   r   r6      s    z4element_text_getter.<locals>._get.<locals>.<genexpr>r   )r   r   r)   vr   r   r   _get   s
   
z!element_text_getter.<locals>._getr   )r   rU   r   rT   r   rC      s   rC   c                    s    fdd}|S )Nc                    s@   t | dkrt fdd| D S t | dkr| d  S S )Nr   c                 3   s    | ]}|  V  qd S r*   )r#   rQ   )r!   r   r   r6     s    z6attribute_text_getter.<locals>._get.<locals>.<genexpr>r   )r   r   r#   rR   r!   r   r   r   rU      s
   z#attribute_text_getter.<locals>._getr   )r!   r   rU   r   rV   r   rD      s   rD   tagutf-8c	              	   C   sx   |s|s|sd}d}d}t | d\}	}
t|	}t|||||||}t|||d}t||||}t|
||d|||d dS )	aH  
    Write the table into a new xml file according to elements defined in the
    function arguments.

    The `root`, `head` and `rows` (string, optional) arguments define the tags
    and the nesting of the xml file. Each one defines xml elements with tags
    separated by slashes (`/`) like in `root/level/tag`. They can have a
    arbitrary number of tags that will reflect in more nesting levels for the
    header or record/row written in the xml file.

    For details on tag naming and nesting rules check xml `specification`_ or
    xml `references`_.

    The `rows` argument define the elements for each row of data to be written
    in the xml file. When specified, it must have at least 2 tags for defining
    the tags for `row/column`. Additional tags will add nesting enclosing all
    records/rows/lines.

    The `head` argument is similar to the rows, but aplies only to one line/row
    of header with fieldnames. When specified, it must have at least 2 tags for
    `fields/name` and the remaining will increase nesting.

    The `root` argument defines the elements enclosing `head` and `rows` and is
    required when using `head` for specifying valid xml documents.

    When none of this arguments are specified, they will default to tags that
    generate output similar to a html table:
    `root='table', head='there/tr/td', rows='tbody/tr/td'`.

    The `prologue` argument (string, optional) could be a snippet of valid xml
    that will be inserted before other elements in the xml. It can optionally
    specify the `XML Prolog` of the file.

    The `epilogue` argument (string, optional) could be a snippet of valid xml
    that will be inserted after all other xml elements except the root closing
    tag. It must specify a closing tag if the `root` argument is not specified. 

    The `style` argument select the format of the elements in the xml file. It
    can be `tag` (default), `name`, `attribute` or a custom string to format
    each row via
    `str.format <http://docs.python.org/library/stdtypes.html#str.format>`_.

    Example usage for writing files::

        >>> import petl as etl
        >>> table1 = [['foo', 'bar'],
        ...           ['a', 1],
        ...           ['b', 2]]
        >>> etl.toxml(table1, 'example.file4.xml')
        >>> # see what we did is similar a html table:
        >>> print(open('example.file4.xml').read())
        <?xml version="1.0" encoding="UTF-8"?>
        <table><thead>
         <tr><th>foo</th><th>bar</th></tr>
        </thead><tbody>
         <tr><td>a</td><td>1</td></tr>
         <tr><td>b</td><td>2</td></tr>
        </tbody></table>
        >>> # define the nesting in xml file:
        >>> etl.toxml(table1, 'example.file5.xml', rows='plan/line/cell')
        >>> print(open('example.file5.xml').read())
        <?xml version="1.0" encoding="UTF-8"?>
        <plan>
         <line><cell>a</cell><cell>1</cell></line>
         <line><cell>b</cell><cell>2</cell></line>
        </plan>
        >>> # choose other style:
        >>> etl.toxml(table1, 'example.file6.xml', rows='row/col', style='attribute')
        >>> print(open('example.file6.xml').read())
        <?xml version="1.0" encoding="UTF-8"?>
        <row>
         <col foo="a" bar="1" />
         <col foo="b" bar="2" />
        </row>
        >>> etl.toxml(table1, 'example.file6.xml', rows='row/col', style='name')
        >>> print(open('example.file6.xml').read())
        <?xml version="1.0" encoding="UTF-8"?>
        <row>
         <col><foo>a</foo><bar>1</bar></col>
         <col><foo>b</foo><bar>2</bar></col>
        </row>

    The `toxml()` function is just a wrapper over :func:`petl.io.text.totext`.
    For advanced cases use a template with `totext()` for generating xml files.

    .. versionadded:: 1.7.0

    .. _specification: https://www.w3.org/TR/xml/
    .. _references: https://www.w3schools.com/xml/xml_syntax.asp

    tablezthead/tr/thztbody/tr/tdr   Tstrict)r   encodingerrorstemplateprologueepilogueN)r   r
   _build_xml_header_build_cols_build_xml_footerr   )rY   targetrootheadrowsr^   r_   styler[   sampletable2propstopr]   bottomr   r   r   toxml
  s   ^

rm   c                 C   s   |rt |dd nd}| dv rdnd}|r/t |d|}	t| ||d}
t |d|}d|	|
|}nd}t |d|}|rI|drId	|||}|| S |rO| nd
}d| }|r]|s]|d nd}|rg|rgd| nd}d||||||}|S )NF 	attributenameTz
{0}
{1}{2}z<?xmlz
{0}{1}{2}
zUTF-8z#<?xml version="1.0" encoding="%s"?>
z{0}
{1}{2}{3}{4}{5}
)_build_nestingra   format
startswithupper)rg   rj   rd   re   rf   r^   r[   tabnestedth1colth2thdtbdthbencxmlpreposresr   r   r   r`   x  s$   r`   c           	      C   s`   | dv rdnd}t |d|}t |dd}|r|r|d nd}|r&|s&d| nd}|| | | S )Nro   rr   rs   Tr   rt   rn   )ru   )	rg   r_   rf   rd   rz   r   ry   r   r   r   r   r   rb     s   rb   c                    sj   | sdS |rdnd d| vr |  S |  d}|r|d| n|}|r'|   fdd|D }d|S )Nrn   z</%s>z<%s>/r   c                    s   g | ]} | qS r   r   rQ   fmtr   r   r3     s    z"_build_nesting.<locals>.<listcomp>)splitreversejoin)pathclosingindexpartselementstagsr   r   r   ru     s   

ru   c                 C   sL   | }| dks	|rt |||dS | dkrt |||dS | dkr$t||S | S )NrW   Trq   Frp   )_build_cols_inline_build_cols_attribs)rg   rj   r   is_value	is_headerr   r   r   ra     s   
ra   c                    s   | d}|r t|dk rtd| |d }|dd d }nd}|d }|r*dnd}d	||  fd
d| D }d|}	d||	}
|
S )Nr   r   zTag not in format 'row/col': %srr   rs   r   z{0}z{{{0}}}z<{0}>{1}</{0}>c                    r-   r   rv   rQ   r   r   r   r3         z&_build_cols_inline.<locals>.<listcomp>rn   z <{0}>{1}</{0}>
)r   r   
ValueErrorrv   r   )rj   r   r   use_tagr   r|   rowfldcolsr   r   r   r   r   r     s   

r   c                    sB   | d}|d }d  fdd| D }d|}d||}|S )Nr   rr   z{0}="{{{0}}}"c                    r-   r   r   rQ   r   r   r   r3     r   z'_build_cols_attribs.<locals>.<listcomp> z <{0} {1} />
)r   r   rv   )rj   r   r   r   r   attsr   r   r   r   r     s   

r   )NNNNNNrW   rX   )#
__future__r   r   r   lxmlr   ImportErrorxml.etree.ElementTreeElementTreeoperatorr   r>   petl.compatr   r   petl.util.baser	   r
   r   petl.io.sourcesr   petl.io.textr   r   r   r;   rC   rD   rm   r`   rb   ru   ra   r   r   r   r   r   r   <module>   s6   ~Q
n	