o bZ@sdZddlZddlmZmZddlmZddlmZddl m Z m Z ddZ d d Z d d Zd ZeeZeedZeeZeefddZefddZGdddeZGdddZGdddeZGdddeZGdddeZGdddeZGdd d eZGd!d"d"eZd#d$Z e Z!Gd%d&d&eZ"Gd'd(d(eZ#d)d*Z$d+d,Z%Gd-d.d.e Z&d/d0Z'd1d2Z(d3d4Z)d5d6Z*Gd7d8d8Z+dS)9a Micro Document Object Model: a partial DOM implementation with SUX. This is an implementation of what we consider to be the useful subset of the DOM. The chief advantage of this library is that, not being burdened with standards compliance, it can remain very stable between versions. We can also implement utility 'pythonic' ways to access and mutate the XML tree. Since this has not subjected to a serious trial by fire, it is not recommended to use this outside of Twisted applications. However, it seems to work just fine for the documentation generator, which parses a fairly representative sample of XML. Microdom mainly focuses on working with HTML and XHTML. N)BytesIOStringIO)ioType)InsensitiveDict) ParseError XMLParsercCsVg}|j}|g}t|dkr)|d}|j|kr|||j|dd<t|dks|S)a3 Return a list of all child elements of C{iNode} with a name matching C{name}. Note that this implementation does not conform to the DOM Level 1 Core specification because it may return C{iNode}. @param iNode: An element at which to begin searching. If C{iNode} has a name matching C{name}, it will be included in the result. @param name: A C{str} giving the name of the elements to return. @return: A C{list} of direct or indirect child elements of C{iNode} with the name C{name}. This may include C{iNode}. rN)appendlenpopnodeName childNodesiNodenamematchesmatches_appendslicecr6/usr/lib/python3/dist-packages/twisted/web/microdom.pygetElementsByTagNames    rcCsb|}g}|j}|g}t|dkr/|d}|j|kr"|||j|dd<t|dks|SNr)lowerrr r r r r rrrgetElementsByTagNameNoCase:s   rcs,ttkrfdd}|Sfdd}|S)Nc"t|tr |d}|dSNzutf-8) isinstancestrencodewritesstreamrrwJ  z_streamWriteWrapper..wcrr)rbytesdecoderr r"rrr$Qr%)rr&)r#r$rr"r_streamWriteWrapperGs   r())&z&)z>)"z"))'z'cCs|D] \}}|||}q|S)z1 Perform the exact opposite of 'escape'. replacetextcharsr!hrrrunescapeh r4cCs|D] \}}|||}q|S)z; Escape a few XML special chars with XML entities. r.r0rrrescapeqr5r6c@s"eZdZddZdefddZdS)MismatchedTagscCs2|||||||f\|_|_|_|_|_|_|_dSN)filenameexpectgotbegLinebegColendLineendCol)selfr9r:r;r>r?r<r=rrr__init__{s zMismatchedTags.__init__returncCs d|j|j|j|j|j|jfS)NzBexpected , got line: %s col: %s, began line: %s col: %s)r:r;r>r?r<r=r@rrr__str__szMismatchedTags.__str__N)__name__ __module__ __qualname__rArrDrrrrr7zs r7c@seZdZdZd"ddZddZddddidfdd Zddddidfd d Zd#ddZd#ddZ d$ddZ ddZ ddZ ddZ ddZddZddZd d!ZdS)%NodeNcCs||_g|_dSr8) parentNoder )r@rIrrrrAs z Node.__init__cCsDt|jt|jkr dSt|j|jD] \}}||sdSqdS)a Compare this node to C{other}. If the nodes have the same number of children and corresponding children are equal to each other, return C{True}, otherwise return C{False}. @type other: L{Node} @rtype: C{bool} FT)r r zip isEqualToNode)r@otherabrrrrKs  zNode.isEqualToNodercCtr8NotImplementedError)r@r#indent addindentnewlstrip nsprefixes namespacerrrwritexmls z Node.writexmlc Cs(t}|||||||||}|Sr8)rrYgetvalue) r@rSrTrUrVrWrXr!rvrrrtoxmlsz Node.toxml  cCs||||||Sr8)rY)r@r#rSrTrUrVrrrwriteprettyxmlzNode.writeprettyxmlcCs|||||Sr8)r\)r@rSrTrUrVrrr toprettyxmlzNode.toprettyxmlcCrPr8rQr@deepparentrrr cloneNodeszNode.cloneNodecCs|jrdSdS)Nrr rCrrr hasChildNodesszNode.hasChildNodescCs(t|ts td|j|||_dS)z Make the given L{Node} the last child of this node. @param child: The L{Node} which will become a child of this node. @raise TypeError: If C{child} is not a C{Node} instance. expected Node instanceN)rrH TypeErrorr rrIr@childrrr appendChilds   zNode.appendChildcCs@t|tr t|tstd|j|}||_|j|||S)a Make the given L{Node} C{new} a child of this node which comes before the L{Node} C{ref}. @param new: A L{Node} which will become a child of this node. @param ref: A L{Node} which is already a child of this node which C{new} will be inserted before. @raise TypeError: If C{new} or C{ref} is not a C{Node} instance. @return: C{new} rj)rrHrkr indexrIinsert)r@newrefirrr insertBefores  zNode.insertBeforecCs2t|ts td||jvr|j|d|_|S)a7 Remove the given L{Node} from this node's children. @param child: A L{Node} which is a child of this node which will no longer be a child of this node after this method is called. @raise TypeError: If C{child} is not a C{Node} instance. @return: C{child} rjN)rrHrkr removerIrlrrr removeChilds   zNode.removeChildcCsPt|tr t|tstd|j|urtd||j|j|<d|_||_dS)a Replace a L{Node} which is already a child of this node with a different node. @param newChild: A L{Node} which will be made a child of this node. @param oldChild: A L{Node} which is a child of this node which will give up its position to C{newChild}. @raise TypeError: If C{newChild} or C{oldChild} is not a C{Node} instance. @raise ValueError: If C{oldChild} is not a child of this C{Node}. rjz$oldChild is not a child of this nodeN)rrHrkrI ValueErrorr ro)r@newChildoldChildrrr replaceChilds  zNode.replaceChildcC |jdSNrhrCrrr lastChild zNode.lastChildcCst|jr |jdSdSr)r r rCrrr firstChilds  zNode.firstChildr8)rOr]r^rrN)rErFrGr rArKrYr\r_rarfrirnrtrvrzr~rrrrrrHs.      rHc@seZdZdddZdddZdZddZeZed d Z d d Z d d d did fddZ ddZ ddZ ddZddZddZdS)DocumentNcCs t||r||dSdSr8)rHrArn)r@documentElementrrrrA0s zDocument.__init__rcCs6t}|j|_|r|jd|}n|j}|||SNrg)rdoctyperrfrn)r@rdrednewElrrrrf5s zDocument.cloneNodecCs|j|jko t||Sr8)rrHrKr@nrrrisEqualToDocumentAszDocument.isEqualToDocumentcCr{rrhrCrrrrFs zDocument.documentElementcCs|jrtdt||dS)a Make the given L{Node} the I{document element} of this L{Document}. @param child: The L{Node} to make into this L{Document}'s document element. @raise ValueError: If this document already has a document element. zOnly one element per document.N)r rwrHrnrlrrrrnJs zDocument.appendChildrOc CsLt|}|d||jr|d|jd||j|||||||dS)Nzz )r(r) r@r#rSrTrUrVrWrXr$valrrrrYs zComment.writexmlNcCrr8)rrrcrrrrfrzComment.cloneNoder)rErFrG__doc__rYrfrrrrrs rc@sLeZdZdddZddZdddZd d d did fd d Zd efd dZdS)rNrcCst|||||_dSr8)rrAraw)r@rrIrrrrrAs z Text.__init__cCst||o |j|jkS)z Compare this text to C{text}. If the underlying values and the C{raw} flag are the same, return C{True}, otherwise return C{False}. )rrKrr@rLrrrrKszText.isEqualToNodecCst|j||jSr8)rrrrcrrrrfrbzText.cloneNoderOc Csht|}|jr|j} t| tst|j} n|j} t| ts!t| } |r*d| } t| } || dS)Nr])r(rrrrjoinsplitr6) r@r#rSrTrUrVrWrXr$rvrrrrYs     z Text.writexmlrBcCsdt|jdS)NzText(%s))reprrrCrrr__repr__r`z Text.__repr__rr) rErFrGrArKrfrYrrrrrrrs   rc@s,eZdZdddZddddidfddZdS) CDATASectionrNcCrr8)rrrcrrrrfrzCDATASection.cloneNoderOc Cs*t|}|d|d|j|ddS)Nz rrrrrrYs  zCDATASection.writexmlr)rErFrGrfrYrrrrrs rccs d} dt|V|d}q)NrTprg)r)rsrrr _genprefixs rc@seZdZdZdS)_Attrz#Support class for getAttributeNode.N)rErFrGrrrrrr src@seZdZdZdZdZ       d(ddZddZdd Zd d Z d d Z d)ddZ ddZ ddZ d*ddZd*ddZddZddZddZddZd d d did fd!d"Zd#efd$d%Zd#efd&d'ZdS)+rrrgNc Cst|||p | |_||_|s|}|duri|_n||_|jD] \} } t| |j| <q%|r;t|j|d|_||_ |_ |_ ||_ ||_ ||_dS)N)preserve)rHrA preserveCaserr attributesitemsr4r endTagNamer tagName _filename_markposrX) r@rrrIr9markposrrrXkrrrrrAs  zElement.__init__cCs$|jdur ||_dS|j|dSr8)rWupdate)r@pfxsrrr addPrefixes5s  zElement.addPrefixescCs|js|}||_dSr8)rrr)r@rrrrendTag;s zElement.endTagcCs>|jr|j|jko|j|jkS|j|jko|j|jkSr8)rrr rrrrrisEqualToElement@s  zElement.isEqualToElementcCs8|j|jko|j|jko|j|jkot||S)z Compare this element to C{other}. If the C{nodeName}, C{namespace}, C{attributes}, and C{childNodes} are all the same, return C{True}, otherwise return C{False}. )r rrXrrHrKrrrrrKGs   zElement.isEqualToNodecsPt|j||j|j|jdj|j|r#fdd|jD_Sg_S)N)rIrXrrcsg|]}|dqS)rg)rf).0rmclonerr ^sz%Element.cloneNode..)rrrXrrrrr rcrrrrfTszElement.cloneNodecCs|jrt||St||Sr8)rrrrrrrrcs  zElement.getElementsByTagNamecCsdSrrrCrrr hasAttributeshszElement.hasAttributescCs|j||Sr8)rget)r@rdefaultrrrrkzElement.getAttributecCs8||f}||jvr|j|S||jkr|j||S|Sr8)rrXr)r@nsrrnskrrrgetAttributeNSns    zElement.getAttributeNScCst|||Sr8)rrrrrrgetAttributeNodevrbzElement.getAttributeNodecCs||j|<dSr8r)r@rattrrrr setAttributeyrzElement.setAttributecCs||jvr |j|=dSdSr8rrrrrremoveAttribute|s  zElement.removeAttributecCs ||jvSr8rrrrr hasAttributerzElement.hasAttributerOc sd}d} d} |js |j|_t|} |jr(|j} |D] } | | vr&| | =qni} dg}|j| vr8||g|}|jfdd}|j}||jkrx|jdurx|j|vri||j}|d|j|d|j}n|j|d |j|j}n|jd j }t |j D]9\}}t |tr|\} }| |vr|| }ntt}|| | <|dusJ||d||q|dusJ|||q| r| D] \} }|r|d || q| || }n|}| |||jr/| d ||}|jD]!}|j| vr |j| vr | |||f||||||||q|j| vr$| |||f| |d |d fdS|j|vrB| |d|d fdS| ddS)a* Serialize this L{Element} to the given stream. @param stream: A file-like object to which this L{Element} will be written. @param nsprefixes: A C{dict} mapping namespace URIs as C{str} to prefixes as C{str}. This defines the prefixes which are already in scope in the document at the point at which this L{Element} exists. This is essentially an implementation detail for namespace support. Applications should not try to use it. @param namespace: The namespace URI as a C{str} which is the default at the point in the document at which this L{Element} exists. This is essentially an implementation detail for namespace support. Applications should not try to use it. ) imgbrhrbasemetalinkparamareainputcolbasefontisindexframe)htmlheadbodynoscriptinsdelh1h2h3h4h5h6scriptuloldlprer blockquoteaddressrdivfieldsettabletrformobjectrappletmap)rrrrr*csd|dt|dfS)Nr]z="r,)r6)_atr_valbextrrsz"Element.writexml..N:xmlnsrOzxmlns:r+z)rrrr(rWcopykeysrrXrsortedrrrtuplenext genprefixrr rYr)r@r#rSrTrUrVrWrXALLOWSINGLETON BLOCKELEMENTS FORMATNICELYr$ newprefixesrbegin writeattrrprefixjrrkey downprefixes newindentrmrrrrYs                     zElement.writexmlrBcCsXdt|j}|jr|d|j7}|jr|d|j7}|jr(|d|j7}|dS)Nz Element(%sz , attributes=z , filename=z , markpos=r)rr rrr)r@reprrrr,szElement.__repr__cCsd|j}|js |jr|d7}|jr|t|j7}|jr#|d|j7}|js)|jr-|d7}|jD]}|d|7}q2|rH|d|j7}|S|d7}|S)Nr*z (z line %s column %srz %s=%rz >...r)r rrrrrri)r@ritemrrrrD6s   zElement.__str__)NNNNrgrNrr8)rErFrGrrrWrArrrrKrfrrrrrrrrrYrrrDrrrrrsF     * rcCs&i}|D] \}}t|||<q|Sr8)rr4rddrrrrr _unescapeDictIsrcCs"i}|D]\}}|||<q|Sr8)rrrrr _reverseDictPs rc@seZdZdZddgddgddgdggdgdgddgdgd gd gd gd gd d gdgdZdddeefddZddZddZe dZ ddZ ddZ ddZdd Zd!d"Zd#d$Zd%d&Zd'd(Zd)d*Zd+d,Zd-S).MicroDOMParserz#area link br img hr input base metardtrli)theadtfoottbodycolgrouprrtdthrroption)rr!rr"r%r#r$r&rrr'r(rtitler)rrgcCsZg|_ddd}t|}|d|fg|_g|_d|_||_||_|p#| |_||_||_ dS)Nr)rrO) elementstackrnsstack documents _mddoctypebeExtremelyLenientrr soonClosers laterClosers)r@r/rrr0r1rdrrrrrAps   zMicroDOMParser.__init__cCsDtt|jD]}|j| }|jdks|dddkrdSqdS)Nrz xml:spacerOrrgr)ranger r+rr)r@edxelrrrshouldPreserveSpaces  z"MicroDOMParser.shouldPreserveSpacecCs|jr|jdSdSr|)r+rCrrr _getparents zMicroDOMParser._getparentz \s*/[/*]\s*c Cs|jr t|jdks dS|}t|trod}|j}|j|}|r.| }|t|d}z t d|jd}Wn t t fyEYdSwt|jdkrOdS|}t|t tfrqg|_|rg|jt||j|dSdSdS)NrgrOz %sr)r/r r rrrrCOMMENTmatchgroup parseStringrr7rrr)r@r5rroldvaluer9errr_fixScriptElements2  z MicroDOMParser._fixScriptElementcCs ||_dSr8)r.)r@rrrr gotDoctyperzMicroDOMParser.gotDoctypec Cs|}|jr/t|tr/|j}|}|jr|}|}||j|gvr/| |j|}t |}|j dd}i}g}| D]%\} } | drg| dd} t| dkr^| || d<n| |d<|| qB|D]} || =qj|r{|}||g}| D])\} } | dd} t| dkr| \} }| dkr| |vr| ||| |f<|| q|D]} || =qt||||j||j|j|dd }t|}|||r|j dd}|||j |||f|j||r|||jr|j|jvr | |dSdSdS) Nr}rrrrgrOxml)rrrX)r7r/rrrrrr1r gotTagEndrr,r startswithrr rr rr9saveMarkrrrr+rnr0)r@rrre parentNamemyName namespaces newspaces keysToDeleterr spacenamesksplitpfxtvr5 revspacesrscopyrrr gotTagStartsx             zMicroDOMParser.gotTagStartcCs>|}|||}|r||dS|jr|j|dSdSr8)r7rnr/r-r)r@factoryrreterrr_gotStandalones zMicroDOMParser._gotStandalonecCs$|s|r|t|dSdSr8)rVr6rSrr@rrrrgotTextszMicroDOMParser.gotTextcC|t|dSr8)rSrrTrrr gotCommentrbzMicroDOMParser.gotCommentcCrVr8)rSr)r@ entityRefrrrgotEntityReferencerbz!MicroDOMParser.gotEntityReferencecCrVr8)rSr)r@cdatarrrgotCData rbzMicroDOMParser.gotCDatac Cs|js|jrdSt|jd|f|d|j}|jdd}|jdd|ur1|j}nd}|jr@|j }| }n|j}|}| dd}t |dkrw|\}} | |d} | durw|j | krw|jswt|j|j|f||j||ks|jr|jr|jd} tt |jD]} |j| d j|kr|j| d |nq|j||dur|j|dS|j| d d=|js|j| dSnt|j|j|f||j|||js|j||jr|jdkr||dSdSdS) NNOTHING)rrr}r@rgrrr)r+r/r7r9rDr r,rrrrr rrXrr3rrr-r>) r@rr5pfxdixnstupletncnamensplitrLnewnamerlastElidxrrrrB sr               zMicroDOMParser.gotTagEndcCs\t|||jr,|jr|j|jddSt|j|jddf||jdj dS)Nrr} END_OF_FILE) rconnectionLostr+r/r-rr7r9rDr)r@reasonrrrrfLs  zMicroDOMParser.connectionLostN)rErFrGrr0r1rAr6r7recompiler8r>r?rPrSrUrWrYr[rBrfrrrrr WsJ  !? @r c Ost|ds t|d}t|i|}t|dd|_|dt|dr*||n|d}|r=|||d}|s1| d|j sMt |jddd |j r}t |j d krm|j d}t|tsltd }|||}ntd }|j D]}||qtn|j d}t|}|j|_|S) z% Parse HTML or XML readable. readrbrz NrZirzNo top-level Nodes in documentrgr)ropenr getattrr9makeConnection dataReceivedrZrjrfr-rr/r rrrnrr.r) readableargskwargsmdprrr5rmdocrrrparse[s>              rvcOsDt|trtt|dg|Ri|Stt|g|Ri|S)NzUTF-16)rrrvrr)strqrrrrr;s  r;cCt|dddSz' Parse an XML readable object. rrgrr)rv)rprrrparseXMLr{cCrxry)r;)rwrrrparseXMLStringr|r}c@sDeZdZdZdddZddZddZd d Zdd d ZddZ dS)lmxz Easy creation of XML. rcCst|tr t|}||_dSr8)rrrr)r@rrrrrAs  z lmx.__init__cs"ddkr tdfddS)Nr_zno private attrscsjfi|Sr8)add)rrr@rrrsz!lmx.__getattr__..)AttributeErrorrrrr __getattr__s zlmx.__getattr__cCs|j||dSr8)rr)r@rrrrr __setitem__r`zlmx.__setitem__cCs |j|Sr8)rr)r@rrrr __getitem__rzlmx.__getitem__rcCst||d}|j||S)N)r)rrrn)r@txtrnnrrrr1s  zlmx.textcKsXt|ddd}|j|t|}|D]\}}|ddkr%|dd}|||<q|S)Nrrzrrg)rrrnr~r)r@rrnewNodexfrrrrrrs    zlmx.addN)r)r) rErFrGrrArrrr1rrrrrr~s   r~),rrhiorrtwisted.python.compatrtwisted.python.utilrtwisted.web.suxrrrrr(HTML_ESCAPE_CHARSlistREV_HTML_ESCAPE_CHARSreverseXML_ESCAPE_CHARSREV_XML_ESCAPE_CHARSr4r6 Exceptionr7rHrrrrrrrrrrrrr rvr;r{r}r~rrrrsT      T +;'