📄 4_tree.html
字号:
the <tt>content</tt> method, you'll need to add the big chunk of code highlighted below, but this is the last big chunk of code in the DOM tutorial!.</p><blockquote> <p></p> <pre>public class DomEcho extends JPanel{ ... public class AdapterNode { ... public String toString() { ... } <new><b>public String content() {</b></new> <new><b>String s = "";</b></new> <new><b>org.w3c.dom.NodeList nodeList = domNode.getChildNodes();</b></new> <new><b>for (int i=0; i<nodeList.getLength(); i++) {</b></new> <new><b>org.w3c.dom.Node node = nodeList.item(i);</b></new> <new><b>int type = node.getNodeType();</b></new> <new><b>AdapterNode adpNode = new AdapterNode(node);</b></new> <new><b>if (type == ELEMENT_TYPE) {</b></new><new><b> </b></new> <new><b>if ( treeElement(node.getNodeName()) ) continue;</b></new> <new></new><new><b>s += "<" + node.getNodeName() + ">";</b></new> <new><b>s += adpNode.content();</b></new> <new><b>s += "</" + node.getNodeName() + ">";</b></new> <new><b>} else if (type == TEXT_TYPE) {</b></new> <new><b>s += node.getNodeValue();</b></new> <new><b>} else if (type == ENTITYREF_TYPE) {</b></new> <new><b>// The content is in the TEXT node under it</b></new> <new><b>s += adpNode.content();</b></new> <new><b>} else if (type == CDATA_TYPE) {</b></new><new></new> <new></new> <new><b>StringBuffer sb = new StringBuffer( node.getNodeValue() );</b></new> <new><b>for (int j=0; j<sb.length(); j++) {</b></new> <new><b>if (sb.charAt(j) == '<') {</b></new> <new><b>sb.setCharAt(j, '&');</b></new> <new><b>sb.insert(j+1, "lt;");</b></new> <new><b>j += 3;</b></new> <new><b>} else if (sb.charAt(j) == '&') {</b></new> <new><b>sb.setCharAt(j, '&');</b></new> <new><b>sb.insert(j+1, "amp;");</b></new> <new><b>j += 4;</b></new> <new><b>}</b></new> <new><b>}</b></new> <new><b>s += "<pre>" + sb + "\n</pre>";</b></new> <new><b>}</b></new> <new><b>}</b></new> <new><b>return s;</b></new> <new><b>}</b></new> ... } // AdapterNode</pre> <p> </blockquote><p><new>This is not the most efficient code anyone ever wrote, but it works and will do fine for our purposes. In this code, you are recognizing and dealing with the following data types:</new></p><dl> <dl> <dt> <b>Element</b></dt> <dd>For elements with names like the XHTML "em" node, you return the node's content sandwiched between the appropriate <em> and </em> tags. However, when processing the content for the <tt>slideshow</tt> element, for example, you don't include tags for the <tt>slide</tt> elements it contains so, when returning a node's content, you skip any subelements that are themselves displayed in the tree.</dd> <dt> </dt> <dd> </dd> <dt><b>Text</b></dt> <dd>No surprise here. For a text node, you simply return the node's <code>value</code>.</dd> <dd> </dd> <dt><b>Entity Reference</b></dt> <dd><new>Unlike CDATA nodes, </new><new></new><new>Entity References can contain multiple subelements. So the strategy here is to return the concatenation of those subelements.</new></dd> <dt> </dt> <dd> </dd> <dt><b>CDATA</b></dt> <dd>Like a text node, you return the node's <code>value</code>. However, since the text in this case may contain angle brackets and ampersands, you need to convert them to a form that displays properly in an HTML pane. Unlike the XML CDATA tag, the HTML <pre> tag does preclude the parsing of character-format tags, break tags and the like. So you have to convert left-angle brackets (<) and ampersands (&) to get them to display properly.</dd> </dl></dl><p> On the other hand, there are quite a few node types you are <i>not</i> processing with the code above. It's worth a moment to examine them and understand why:</p><dl> <dl> <dt><new></new><new><b>Attribute</b></new></dt> <dd><b><new> </new></b><new>These</new><new> nodes do not appear in the DOM, but are obtained by invoking <tt>getAttributes</tt> on element nodes.</new></dd> <dt><new><b><br> Entity </b></new></dt> <dd><new>These nodes also do not appear in the DOM</new>. They are obtained by invoking <tt>getEntities</tt> on DocType nodes.<new></new></dd> <dt><new><b><br> Processing Instruction</b></new></dt> <dd><new>These nodes don't contain displayable data.</new><new></new></dd> <dt><new><b><br> Comment </b></new></dt> <dd><new>Ditto. Nothing you want to display here.</new></dd> <dt> <new><b><br> Document</b></new></dt> <dd><new>This is the root node for the DOM. There's no data to display for that.</new></dd> <dt> <new><b><br> DocType</b></new></dt> <dd><new>The DocType node contains the DTD specification, with or without external pointers. It only appears under the root node, and has no data to display in the tree.</new></dd> <dt><new><b></b></new> <new><b><br> Document Fragment</b></new></dt> <dd><new>This node is equivalent to a document node. It's a root node that the DOM specification intends for holding intermediate results during cut/paste operations, for example. Like a document node, there's no data to display.</new></dd> <dt> </dt> <dt><new><b></b></new></dt> <dt><new><b> Notation</b></new></dt> <dd><new>We're just flat out ignoring this one. These nodes are used to include binary data in the DOM. As discussed earlier in <a href="../sax/5d_dtd.html">Referencing Binary Entities</a> and <a href="../sax/9_notatn.html">Using the DTDHandler and EntityResolver</a>, the MIME types (in conjunction with namespaces) make a better mechanism for that.</new> </dd> </dl></dl><h4><a name="content"></a>Display the Content in the JTree</h4><p>With the content-concatenation out of the way, only a few small programming steps remain. The first is to modify <tt>toString</tt> so that it uses the node's content for identifying information. Add the code highlighted below to do that: </p><blockquote> <p></p> <pre>public class DomEcho extends JPanel{ ... public class AdapterNode { ... public String toString() { ... if (! nodeName.startsWith("#")) { s += ": " + nodeName; } <new><b>if (compress) {</b></new> <new><b>String t = content().trim();</b></new> <new><b>int x = t.indexOf("\n");</b></new> <new><b>if (x >= 0) t = t.substring(0, x);</b></new> <new><b>s += " " + t;</b></new> <new><b>return s;</b></new> <new><b>}</b></new> if (domNode.getNodeValue() != null) { ... } return s; } </pre> <p> </blockquote><h4><a name="wire"></a>Wire the JTree to the JEditorPane</h4><p>Returning now to the app's constructor, create a tree selection listener and use to wire the JTree to the JEditorPane:</p><blockquote> <p></p> <pre>public class DomEcho extends JPanel{ ... public DomEcho() { ... // Build right-side view <new></new><new></new>JEditorPane htmlPane = new JEditorPane("text/html",""); htmlPane.setEditable(false); JScrollPane htmlView = new JScrollPane(htmlPane); htmlView.setPreferredSize( new Dimension( rightWidth, windowHeight )); <new></new><new></new><new><b>tree.addTreeSelectionListener(</b></new> <new><b>new TreeSelectionListener() {</b></new> <new><b>public void valueChanged(TreeSelectionEvent e) {</b></new> <new><b>TreePath p = e.getNewLeadSelectionPath();</b></new> <new><b>if (p != null) {</b></new> <new><b>AdapterNode adpNode = </b></new> <new><b>(AdapterNode) p.getLastPathComponent();</b></new> <new><b>htmlPane.setText(adpNode.content());</b></new> <new><b>}</b></new> <new><b>}</b></new> <new><b>}</b></new> <new><b>);</b></new> </pre> <p> <p> </blockquote><blockquote> <p> </blockquote><p>Now, when a JTree node is selected, it's contents are delivered to the <code>htmlPane</code>. <new> </new> <new></new></p><blockquote> <p><new><b>Note:</b><br> The TreeSelectionListener in this example is created using an anonymous inner-class adapter. If you are programming for the 1.1 version of the platform, you'll need to define an external class for this purpose.</new></p></blockquote><p>If you compile this version of the app, you'll discover immediately that the <tt>htmlPane</tt> needs to be specified as <tt>final</tt> to be referenced in an inner class, so add the keyword highlighted below:</p><blockquote> <pre>public DomEcho04(){ ... // Build right-side view <new><b>final </b></new>JEditorPane htmlPane = new JEditorPane("text/html",""); htmlPane.setEditable(false); JScrollPane htmlView = new JScrollPane(htmlPane); htmlView.setPreferredSize( new Dimension( rightWidth, windowHeight ));</pre></blockquote><h4><a name="run"></a>Run the App</h4><blockquote> <p></blockquote><blockquote> <p> </blockquote><blockquote> <p> </blockquote><p>When you compile the app and run it on <a href="samples/slideSample10.xml"><code>slideSample10.xml</code></a>, you get a display like that shown in Figure 2. Expanding the hierarchy shows that the JTree now includes identifying text for a node whenever possible.</p><blockquote> <p><img src="images/p410b.gif" width="640" height="440"><br> <i><b>Figure 2: Collapsed Hierarchy Showing Text in Nodes</b></i></p></blockquote><blockquote> <p> </blockquote><p>Selecting an item that includes XHTML subelements produces a display like that shown in Figure 3:</p><blockquote> <p><img src="images/p410c.gif" width="640" height="440"><br> <i><b>Figure 3: Node with <em> Tag Selected</b></i></p></blockquote><p>Selecting a node that contains an entity reference causes the entity text to be included, as shown in Figure 4: </p><blockquote> <p> <img src="images/p410d.gif" width="640" height="440"><br> <i><b>Figure 4: Node with Entity Reference Selected</b></i></p></blockquote><p></p><blockquote> <p> </blockquote><blockquote> <p> </blockquote><p>Finally, selecting a node that includes a CDATA section produces results like those shown in Figure 5:</p><blockquote> <p><img src="images/p410e.gif" width="640" height="440"><br> <i><b>Figure 5: Node with CDATA Component Selected</b></i></p></blockquote><p></p><p></p><h4><new><a name="extra2"></a>Extra Credit</new></h4><p><new>Now that you have the app working, here are some ways you might think about extending it in the future:</new></p><dl> <dl> <dt><new><b>Use Title Text to Identify Slides</b></new></dt> <dd><new></new><new></new><new> Special case the <tt>slide</tt> element so that the contents of the <tt>title</tt> node is used as the identifying text. When selected, convert the title node's contents to a centered H1 tag, and </new><new>ignore the <tt>title</tt> element when constructing the tree.</new></dd> <dt> </dt> <dt><b>Convert Item Elements to Lists</b></dt> <dd><new></new><new>Remove <tt>item</tt> elements from the JTree and convert them to html lists using</new> <new> <ul>, <li>, </ul> tags</new>, including them in the slide's content when the slide is selected.<new></new></dd> </dl></dl><p></p><h3><a name="mods"></a>Handling Modifications</h3><p>A full discussion of the mechanisms for modifying the JTree's underlying data model is beyond the scope of this tutorial. However, a few words on the subject are in order.</p><p>Most importantly, note that if you allow the user to modifying the structure by manipulating the JTree, you have take the compression into account when you figure out where to apply the change. For example, if you are displaying text in the tree and the user modifies that, the changes would have to be applied to text subelements, and perhaps require a rearrangement of the XHTML subtree.</p><p>When you make those changes, you'll need to understand more about the interactions between a JTree, it's TreeModel, and an underlying data model. That subject is covered in depth in the Swing Connection article, <a href="http://java.sun.com/products/jfc/tsc/articles/jtree/index.html">Understanding the TreeModel</a>.<new></new></p><h3><a name="finish"></a>Finishing Up</h3><p>You now understand pretty much what there is know about the structure of a DOM, and you know how to adapt a DOM to create a user-friendly display in a JTree. It has taken quite a bit of coding, but in return you have obtained valuable tools for exposing a DOM's structure and a template for GUI apps. In the next section, you'll make a couple of minor modifications to the code that turn the app into a vehicle for experimentation, and then experiment with building and manipulating a DOM.<blockquote> <p> <hr size=4></blockquote><p> <p> <table width="100%"> <tr> <td align=left> <ahref="3_display.html"><img src="../images/PreviousArrow.gif" width=26 height=26 align=bottom border=0 alt="Previous | "></a><a href="5_create.html"><img src="../images/NextArrow.gif" width=26 height=26 align=bottom border=0 alt="Next | "></a><a href="../alphaIndex.html"><img src="../images/xml_IDX.gif" width=26 height=26 align=top border=0 alt="Index | "></a><a href="../TOC.html"><imgsrc="../images/xml_TOC.gif" width=26 height=26 align=top border=0 alt="TOC | "></a><a href="../index.html"><imgsrc="../images/xml_Top.gif" width=26 height=26 align=top border=0 alt="Top | "></a> </td> <td align=right><strong><em><a href="index.html">Top</a></em></strong> <a href="../TOC.html#intro"><strong><em>Contents</em></strong></a> <a href="../TOC.html#intro"><strong><em></em></strong></a> <a href="../alphaIndex.html"><strong><em>Index</em></strong></a> <a href="../glossary.html"><strong><em>Glossary</em></strong></a></td> </tr></table></body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -