📄 index.lxp@lxpwrap=x1807_252ehtm.htm
字号:
xmllib to parse documents that contain references to Unicode characters.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#DH5"><IMGSRC="images/callouts/6.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(6)"></A></DT><DD>XML has the same kind of comments as HTML. Most parsers simply pass the comments, but if you want to show them (for instance, in a structured view of an XML document) or if you want to preserve the contents of the file exactly, you can connect a slot to the signal emitted by this function. </DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#DH6"><IMGSRC="images/callouts/7.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(7)"></A></DT><DD>CDATA is literal data enclosed between <TTCLASS="LITERAL"><![CDATA[</TT> and <TTCLASS="LITERAL">]]></TT>. A file containing </DD><PRECLASS="SCREEN"><![CDATA[surely you will be allowed tostarve to death in one of the royal parks.]]> </PRE><DD><P>will present the quote ‘surely you will be allowed to starve to death in one of the royal parks.' to any slot that is connected to <TTCLASS="FUNCTION">sigCData</TT>.</P></DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#DH7"><IMGSRC="images/callouts/8.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(8)"></A></DT><DD>This is called when the XML document contains processing instructions. A processing instruction begins with <?. All special cases, such as the XML declaration itself, are handled by other methods. </DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#DH8"><IMGSRC="images/callouts/9.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(9)"></A></DT><DD>You can declare entities in XML — references to something externally defined. Those start with <!. The contents of the declaration will be passed on in the <TTCLASS="VARNAME">data</TT> argument. </DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#DH9"><IMGSRC="images/callouts/10.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(10)"></A></DT><DD>XML is far less forgiving than HTML (or at least, XML has both a stricter definition and less easy-going parsers), and whenever an error is encountered, such as forgetting to close a tag, this method is called. </DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#DH10"><B>(11)</B></A></DT><DD> <TTCLASS="FUNCTION">unknown_starttag</TT> is the most interesting method in the <TTCLASS="CLASSNAME">xmllib.XMLParser</TT> class. This is called whenever the xmllib parser encounters a plain tag that is not present in its <TTCLASS="VARNAME">elements</TT> dictionary. That is, it will be called for all elements in our current implementation.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#DH11"><B>(12)</B></A></DT><DD>Likewise, <TTCLASS="FUNCTION">unknown_endtag</TT> is called for the corresponding ending tags. </DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#DH12"><B>(13)</B></A></DT><DD>Whenever the parser encounters an unresolvable numeric character reference, this function is called. </DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#DH13"><B>(14)</B></A></DT><DD>Unknown entities are forbidden in XML — if you use an entity somewhere in your document (which you can do by placing the name of the entity between an ampersand and a semicolon), then it must be declared. However, you might want to catch occurrences of unknown entities and do something special. That's why the function <TTCLASS="FUNCTION">unknown_entityref</TT> is implemented here. By default <TTCLASS="FUNCTION">unknown_entityref</TT> calls the <TTCLASS="FUNCTION">syntax_error()</TT> function of <TTCLASS="CLASSNAME">xmllib.XMLParser</TT>. </DD></DL></DIV><P>The <TTCLASS="CLASSNAME">TreeView</TT> class will show the contents of the XML file.</P><PRECLASS="PROGRAMLISTING">class TreeView(QListView): <IMGSRC="images/callouts/1.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(1)"></A> def __init__(self, *args): apply(QListView.__init__,(self, ) + args) self.stack=[] <IMGSRC="images/callouts/2.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(2)"></A> self.setRootIsDecorated(TRUE) <IMGSRC="images/callouts/3.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(3)"></A> self.addColumn("Element") <IMGSRC="images/callouts/4.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(4)"></A> def startDocument(self, tag, pubid, syslit, data): <IMGSRC="images/callouts/5.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(5)"></A> i=QListViewItem(self) if tag == None: tag = "None" i.setText(0, tag) self.stack.append(i) def startElement(self, tag, attributes): <IMGSRC="images/callouts/6.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(6)"></A> if tag == None: tag = "None" i=QListViewItem(self.stack[-1]) i.setText(0, tag) self.stack.append(i) def endElement(self, tag): <IMGSRC="images/callouts/7.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(7)"></A> del(self.stack[-1]) </PRE><DIVCLASS="CALLOUTLIST"><DLCOMPACT="COMPACT"><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#TVCLASS"><IMGSRC="images/callouts/1.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(1)"></A></DT><DD>The <TTCLASS="CLASSNAME">TreeView</TT> class is a simple subclass of PyQt's versatile <TTCLASS="CLASSNAME">QListView</TT> class.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#TVSTACK"><IMGSRC="images/callouts/2.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(2)"></A></DT><DD>Because XML is a hierarchical file format, elements are neatly nested in each other. In order to be able to create the right treeview, we should keep a stack of the current element depth. The last element of the stack will be the parent element of all new elements.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#TVDECORATION"><IMGSRC="images/callouts/3.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(3)"></A></DT><DD>This option sets the beginning of the tree at the first element, making it clear to the user that it's an expandable tree instead of a simple list.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#TVCOLS"><IMGSRC="images/callouts/4.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(4)"></A></DT><DD>We present only one column in the listview — if you want to show the attributes of elements, too, you might add a few more columns.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#TVF1"><IMGSRC="images/callouts/5.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(5)"></A></DT><DD>The <TTCLASS="FUNCTION">startDocument</TT> function is called when the XML document is opened. It also starts the call stack by creating the first element. The first <TTCLASS="CLASSNAME">QListViewItem</TT> object has the listview as a parent; all others with have a <TTCLASS="CLASSNAME">QListViewItem</TT> object as parent. The constructor of <TTCLASS="CLASSNAME">QListViewItem</TT> is so overloaded that sip tends to get confused, so I create the item and set its text separately.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#TVF2"><IMGSRC="images/callouts/6.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(6)"></A></DT><DD>Whenever an element is opened, a <TTCLASS="CLASSNAME">QListViewItem</TT> item is created and pushed on the stack, where it becomes the parent for newly opened elements.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#TVF3"><IMGSRC="images/callouts/7.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(7)"></A></DT><DD>Conversely, when the element is closed, it is popped <SPAN><ICLASS="EMPHASIS">from</I></SPAN> the stack.</DD></DL></DIV><PRECLASS="PROGRAMLISTING">def main(args): if (len(args) == 2): app = QApplication(sys.argv) QObject.connect(app, SIGNAL('lastWindowClosed()'), app, SLOT('quit()')) w = TreeView() app.setMainWidget(w) o=QObject() <IMGSRC="images/callouts/1.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(1)"></A> p=Parser(o) <IMGSRC="images/callouts/2.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(2)"></A> QObject.connect(o, PYSIGNAL("sigDocType"), <IMGSRC="images/callouts/3.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(3)"></A> w.startDocument) QObject.connect(o, PYSIGNAL("sigStartTag"), w.startElement) QObject.connect(o, PYSIGNAL("sigEndTag"), w.endElement) s=open(args[1]).read() <IMGSRC="images/callouts/4.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(4)"></A> p.start(s) w.show() app.exec_loop() else: print "Usage: python qtparser.py FILE.xml"if __name__=="__main__": main(sys.argv) </PRE><DIVCLASS="CALLOUTLIST"><DLCOMPACT="COMPACT"><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#QOBJECT"><IMGSRC="images/callouts/1.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(1)"></A></DT><DD>Here we create a <TTCLASS="CLASSNAME">QObject</TT> which is used to emit all necessary signals, since we cannot inherit from more than one PyQt class at the same time. Note that by using this technique, you don't have to subclass from <TTCLASS="CLASSNAME">QObject</TT> in order to be able to emit signals. Sometimes delegation works just as well.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#PARSER"><IMGSRC="images/callouts/2.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(2)"></A></DT><DD>A parser object is created, with the <TTCLASS="CLASSNAME">QObject</TT> object as its argument.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#CONNECTIONS"><IMGSRC="images/callouts/3.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(3)"></A></DT><DD>Before feeding the parser the text, all connections we want are made from the <TTCLASS="CLASSNAME">QObject</TT> object (which we passed to the parser to make sure it can emit signals) to the <TTCLASS="CLASSNAME">TreeView</TT> object that forms the main window.</DD><DT><A href="index.lxp@lxpwrap=x1807_252ehtm.htm#READING"><IMGSRC="images/callouts/4.gif"HSPACE="0"VSPACE="0"BORDER="0"ALT="(4)"></A></DT><DD>The file whose name was given on the command line is read and passed on to the parser. I have included a very small test file, <TTCLASS="FILENAME">test.xml</TT>, but you can use any Designer UI design file.</DD></DL></DIV></DIV><P>This is a very simple and convenient way of working with XML files and PyQt gui's — but it's generally useful, too. The standard way of working with XML files and parsers allows for only one function to be called for each tag. Using signals and slots, you can have as many slots connected to each signal as you want. For instance, you can have not only a gui, but also an analyzer that produces statistics listening in on the same parsing run.</P><DIVCLASS="MEDIAOBJECT"><P><DIVCLASS="CAPTION"><P>The result of parsing a Designer .ui file.</P></DIV></P></DIV><P>On a final note, there is one bug in this code... See if you can find it, or consult <A href="index.lxp@lxpwrap=x3270_252ehtm.htm#CH2LISTVIEW">the Section called <I>QListView and QListViewItem</I> in Chapter 10</A> for an explanation.</P></DIV><DIVCLASS="NAVFOOTER"><HRALIGN="LEFT"WIDTH="100%"><TABLESUMMARY="Footer navigation table"WIDTH="100%"BORDER="0"CELLPADDING="0"CELLSPACING="0"><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top"><A accesskey="P" href="index.lxp@lxpwrap=x1631_252ehtm.htm">Prev</A></TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="H" href="index.lxp@lxpwrap=book1_252ehtm">Home</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top"><A accesskey="N" href="index.lxp@lxpwrap=x2026_252ehtm.htm">Next</A></TD></TR><TR><TDWIDTH="33%"ALIGN="left"VALIGN="top">Disconnecting</TD><TDWIDTH="34%"ALIGN="center"VALIGN="top"><A accesskey="U" href="index.lxp@lxpwrap=c1267_252ehtm.htm">Up</A></TD><TDWIDTH="33%"ALIGN="right"VALIGN="top">Conclusion</TD></TR></TABLE></DIV></BODY></HTML> </td> </tr> </table> </td> </tr> </table>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -