⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 jaxpdom4.html

📁 j2eePDF格式的电子书
💻 HTML
📖 第 1 页 / 共 3 页
字号:
<code class="cCodeBold">public class AdapterNode { &nbsp;&nbsp;org.w3c.dom.Node domNode;&nbsp;&nbsp;// Construct an Adapter node from a DOM node&nbsp;&nbsp;public AdapterNode(org.w3c.dom.Node node) {&nbsp;&nbsp;&nbsp;&nbsp;domNode = node;&nbsp;&nbsp;}&nbsp;&nbsp;// Return a string that identifies this node&nbsp;&nbsp;// &nbsp;&nbsp;&nbsp;&nbsp;in the tree&nbsp;&nbsp;public String toString() {&nbsp;&nbsp;&nbsp;&nbsp;String s = typeName[domNode.getNodeType()];&nbsp;&nbsp;&nbsp;&nbsp;String nodeName = domNode.getNodeName();&nbsp;&nbsp;&nbsp;&nbsp;if (! nodeName.startsWith(&quot;#&quot;)) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s += &quot;: &quot; + nodeName;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;if (domNode.getNodeValue() != null) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (s.startsWith(&quot;ProcInstr&quot;)) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s += &quot;, &quot;; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s += &quot;: &quot;;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// Trim the value to get rid of NL&#39;s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;at the front&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String t = domNode.getNodeValue().trim();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;int x = t.indexOf(&quot;);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (x &gt;= 0) t = t.substring(0, x);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s += t;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;return s;&nbsp;&nbsp;}}</code> // AdapterNode} // DomEcho <a name="wp64409"> </a></pre></div><a name="wp66741"> </a><p class="pBody">This class declares a variable to hold the DOM node, and requires it to be specified as a constructor argument. It then defines the <code class="cCode">toString</code> operation, which returns the node type from the <code class="cCode">String</code> array, and then adds to that additional information from the node, to further identify it.</p><a name="wp64415"> </a><p class="pBody">As you can see in the table of node types in <code class="cCode">org.w3c.dom.Node</code>, every node has a type, and name, and a value, which may or may not be empty. In those cases where the node name starts with <code class="cCode">&quot;#&quot;</code>, that field duplicates the node type, so there is in point in including it. That explains the lines that read:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">if (! nodeName.startsWith(&quot;#&quot;)) {&nbsp;&nbsp;s += &quot;: &quot; + nodeName;} <a name="wp64416"> </a></pre></div><a name="wp64417"> </a><p class="pBody">The remainder of the <code class="cCode">toString</code> method deserves a couple of notes, as well. For instance, these lines:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">if (s.startsWith(&quot;ProcInstr&quot;)) &nbsp;&nbsp;s += &quot;, &quot;; else &nbsp;&nbsp;s += &quot;: &quot;;<a name="wp64418"> </a></pre></div><a name="wp64419"> </a><p class="pBody">Merely provide a little &quot;syntactic sugar&quot;. The type field for a Processing Instructions end with a colon (:) anyway, so those codes keep from doubling the colon.</p><a name="wp64420"> </a><p class="pBody">The other interesting lines are:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">String t = domNode.getNodeValue().trim();int x = t.indexOf(&quot;);if (x &gt;= 0) t = t.substring(0, x);s += t;<a name="wp64421"> </a></pre></div><a name="wp64422"> </a><p class="pBody">Those lines trim the value field down to the first newline (linefeed) character in the field. If you leave those lines out, you will see some funny characters (square boxes, typically) in the <code class="cCode">JTree</code>. </p><hr><a name="wp64423"> </a><p class="pNote">Note: Recall that XML stipulates that all line endings are normalized to newlines, regardless of the system the data comes from. That makes programming quite a bit simpler. </p><hr><a name="wp64424"> </a><p class="pBody">Wrapping a <code class="cCode">DomNode</code> and returning the desired string are the <code class="cCode">AdapterNode</code>'s major functions. But since the <code class="cCode">TreeModel</code> adapter will need to answer questions like &quot;How many children does this node have?&quot; and satisfy commands like &quot;Give me this node's Nth child&quot;, it will be helpful to define a few additional utility methods. (The adapter could always access the DOM node and get that information for itself, but this way things are more encapsulated.)</p><a name="wp64425"> </a><p class="pBody">Next, add the code highlighted below to return the index of a specified child, the child that corresponds to a given index, and the count of child nodes:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">public class AdapterNode { &nbsp;&nbsp;...&nbsp;&nbsp;public String toString() {&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;}<a name="wp64426"> </a>&nbsp;&nbsp;<code class="cCodeBold">public int index(AdapterNode child) {&nbsp;&nbsp;&nbsp;&nbsp;//System.err.println(&quot;Looking for index of &quot; + child);&nbsp;&nbsp;&nbsp;&nbsp;int count = childCount();&nbsp;&nbsp;&nbsp;&nbsp;for (int i=0; i&lt;count; i++) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AdapterNode n = this.child(i);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (child == n) return i;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;&nbsp;return -1; // Should never get here.&nbsp;&nbsp;}&nbsp;&nbsp;public AdapterNode child(int searchIndex) {&nbsp;&nbsp;&nbsp;&nbsp;//Note: JTree index is zero-based. &nbsp;&nbsp;&nbsp;&nbsp;org.w3c.dom.Node node =&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;domNode.getChildNodes().item(searchIndex);&nbsp;&nbsp;&nbsp;&nbsp;return new AdapterNode(node); &nbsp;&nbsp;}&nbsp;&nbsp;public int childCount() {&nbsp;&nbsp;&nbsp;&nbsp;return domNode.getChildNodes().getLength(); &nbsp;&nbsp;}</code>} // AdapterNode<a name="wp64427"> </a>} // DomEcho<a name="wp64428"> </a></pre></div><hr><a name="wp64429"> </a><p class="pNote">Note: During development, it was only after I started writing the <code class="cCode">TreeModel</code> adapter that I realized these were needed, and went back to add them. In just a moment, you'll see why. </p><hr><a name="wp64431"> </a><h4 class="pHeading3">Define the TreeModel Adapter</h4><a name="wp64432"> </a><p class="pBody">Now, at last, you are ready to write the <code class="cCode">TreeModel</code> adapter. One of the really nice things about the <code class="cCode">JTree</code> model is the relative ease with which you convert an existing tree for display. One of the reasons for that is the clear separation between the displayable view, which <code class="cCode">JTree</code> uses, and the modifiable view, which the application uses. For more on that separation, see Understanding the TreeModel at <code class="cCode">http://java.sun.com/products/jfc/tsc/articles/jtree/index.html</code>. For now, the important point is that to satisfy the <code class="cCode">TreeModel</code> interface we only need to (a) provide methods to access and report on children and (b) register the appropriate <code class="cCode">JTree</code> listener, so it knows to update its view when the underlying model changes.</p><a name="wp64433"> </a><p class="pBody">Add the code highlighted below to create the <code class="cCode">TreeModel</code> adapter and specify the child-processing methods:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">&nbsp;&nbsp;...} // AdapterNode<a name="wp64434"> </a>// This adapter converts the current Document (a DOM) into // a JTree model. <code class="cCodeBold">public class DomToTreeModelAdapter implements javax.swing.tree.TreeModel {&nbsp;&nbsp;// Basic TreeModel operations&nbsp;&nbsp;public Object  getRoot() {&nbsp;&nbsp;&nbsp;&nbsp;//System.err.println(&quot;Returning root: &quot; +document);&nbsp;&nbsp;&nbsp;&nbsp;return new AdapterNode(document);&nbsp;&nbsp;}&nbsp;&nbsp;public boolean isLeaf(Object aNode) {&nbsp;&nbsp;&nbsp;&nbsp;// Determines whether the icon shows up to the left.&nbsp;&nbsp;&nbsp;&nbsp;// Return true for any node with no children&nbsp;&nbsp;&nbsp;&nbsp;AdapterNode node = (AdapterNode) aNode;&nbsp;&nbsp;&nbsp;&nbsp;if (node.childCount() &gt; 0) return false;&nbsp;&nbsp;&nbsp;&nbsp;return true;&nbsp;&nbsp;}&nbsp;&nbsp;public int     getChildCount(Object parent) &nbsp;&nbsp;&nbsp;&nbsp;AdapterNode node = (AdapterNode) parent;&nbsp;&nbsp;&nbsp;&nbsp;return node.childCount();&nbsp;&nbsp;}&nbsp;&nbsp;public Object  getChild(Object parent, int index) {&nbsp;&nbsp;&nbsp;&nbsp;AdapterNode node = (AdapterNode) parent;&nbsp;&nbsp;&nbsp;&nbsp;return node.child(index);&nbsp;&nbsp;}&nbsp;&nbsp;public int     getIndexOfChild(Object parent, Object child) {&nbsp;&nbsp;&nbsp;&nbsp;AdapterNode node = (AdapterNode) parent;&nbsp;&nbsp;&nbsp;&nbsp;return node.index((AdapterNode) child);&nbsp;&nbsp;}&nbsp;&nbsp;public void valueForPathChanged(&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreePath path, Object newValue) &nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;// Null. We won&#39;t be making changes in the GUI&nbsp;&nbsp;&nbsp;&nbsp;// If we did, we would ensure the new value was&nbsp;&nbsp;&nbsp;&nbsp;// really new and then fire a TreeNodesChanged event.&nbsp;&nbsp;}}</code> // DomToTreeModelAdapter} // DomEcho  <a name="wp66797"> </a></pre></div><a name="wp64436"> </a><p class="pBody">In this code, the <code class="cCode">getRoot</code> method returns the root node of the DOM, wrapped as an <code class="cCode">AdapterNode</code> object. From here on, all nodes returned by the adapter will be <code class="cCode">AdapterNodes</code> that wrap DOM nodes. By the same token, whenever the <code class="cCode">JTree</code> asks for the child of a given parent, the number of children that parent has, etc., the <code class="cCode">JTree</code> will be passing us an <code class="cCode">AdapterNode</code>. We know that, because we control every node the <code class="cCode">JTree</code> sees, starting with the root node. </p><a name="wp64437"> </a><p class="pBody"><code class="cCode">JTree</code> uses the <code class="cCode">isLeaf</code> method to determine whether or not to display a clickable expand/contract icon to the left of the node, so that method returns true only if the node has children. In this method, we see the cast from the generic object <code class="cCode">JTree</code> sends us to the <code class="cCode">AdapterNode</code> object we know it has to be. <em class="cEmphasis">We</em> know it is sending us an adapter object, but the interface, to be general, defines objects, so we have to do the casts. </p><a name="wp64438"> </a><p class="pBody">The next three methods return the number of children for a given node, the child that lives at a given index, and the index of a given child, respectively. That's all pretty straightforward. </p><a name="wp64439"> </a><p class="pBody">The last method is invoked when the user changes a value stored in the <code class="cCode">JTree</code>. In this app, we won't support that. But if we did, the application would have to make the change to the underlying model and then inform any listeners that a change had occurred. (The <code class="cCode">JTree</code> might not be the only listener. In many an application it isn't, in fact.) </p><a name="wp64440"> </a><p class="pBody">To inform listeners that a change occurred, you'll need the ability to register them. That brings us to the last two methods required to implement the <code class="cCode">TreeModel</code> interface. Add the code highlighted below to define them: </p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">public class DomToTreeModelAdapter ...{&nbsp;&nbsp;...&nbsp;&nbsp;public void valueForPathChanged(&nbsp;&nbsp;&nbsp;&nbsp;TreePath path, Object newValue)&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;}&nbsp;&nbsp;<code class="cCodeBold">private Vector listenerList = new Vector();&nbsp;&nbsp;public void addTreeModelListener(&nbsp;&nbsp;&nbsp;&nbsp;TreeModelListener listener ) {&nbsp;&nbsp;&nbsp;&nbsp;if ( listener != null &nbsp;&nbsp;&nbsp;&nbsp;&amp;&amp; ! listenerList.contains(listener) ) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listenerList.addElement( listener );&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;}&nbsp;&nbsp;public void removeTreeModelListener( &nbsp;&nbsp;&nbsp;&nbsp;TreeModelListener listener ) &nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;if ( listener != null ) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listenerList.removeElement( listener );&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;}</code>} // DomToTreeModelAdapter<a name="wp66820"> </a></pre></div><a name="wp64442"> </a><p class="pBody">Since this application won't be making changes to the tree, these methods will go unused, for now. However, they'll be there in the future, when you need them.    </p><hr><a name="wp64443"> </a><p class="pNote">Note: This example uses <code class="cCode">Vector</code> so it will work with 1.1 apps. If coding for 1.2 or later, though, I'd use the excellent collections framework instead:<br />&nbsp;&nbsp;private LinkedList listenerList = new LinkedList();</p><hr><a name="wp64445"> </a><p class="pBody">The operations on the <code class="cCode">List</code> are then <code class="cCode">add</code> and <code class="cCode">remove</code>. To iterate over the list, as in the operations below, you would use:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">Iterator it = listenerList.iterator();while ( it.hasNext() ) {&nbsp;&nbsp;TreeModelListener listener = (TreeModelListener) it.next();&nbsp;&nbsp;&nbsp;&nbsp;... }<a name="wp64446"> </a></pre></div><a name="wp64447"> </a><p class="pBody">Here, too, are some optional methods you won't be using in this application. At this point, though, you have constructed a reasonable template for a TreeModel adapter. In the interests of completeness, you might want to add the code highlighted below. You can then invoke them whenever you need to notify <code class="cCode">JTree</code> listeners of a change:   </p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">&nbsp;&nbsp;public void removeTreeModelListener( &nbsp;&nbsp;&nbsp;&nbsp;TreeModelListener listener) &nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;...&nbsp;&nbsp;} &nbsp;&nbsp;<code class="cCodeBold">public void fireTreeNodesChanged( TreeModelEvent e ) {&nbsp;&nbsp;&nbsp;&nbsp;Enumeration listeners = listenerList.elements();&nbsp;&nbsp;&nbsp;&nbsp;while ( listeners.hasMoreElements() ) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeModelListener listener = &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(TreeModelListener) listeners.nextElement();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listener.treeNodesChanged( e );&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;}&nbsp;&nbsp;public void fireTreeNodesInserted( TreeModelEvent e ) {&nbsp;&nbsp;&nbsp;&nbsp;Enumeration listeners = listenerList.elements();&nbsp;&nbsp;&nbsp;&nbsp;while ( listeners.hasMoreElements() ) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeModelListener listener = &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(TreeModelListener) &nbsp;&nbsp;listeners.nextElement();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listener.treeNodesInserted( e );&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;} &nbsp;&nbsp;public void fireTreeNodesRemoved( TreeModelEvent e ) {&nbsp;&nbsp;&nbsp;&nbsp;Enumeration listeners = listenerList.elements();&nbsp;&nbsp;&nbsp;&nbsp;while ( listeners.hasMoreElements() ) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeModelListener listener = &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(TreeModelListener) listeners.nextElement();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listener.treeNodesRemoved( e );&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;} &nbsp;&nbsp;public void fireTreeStructureChanged( TreeModelEvent e ) {&nbsp;&nbsp;&nbsp;&nbsp;Enumeration listeners = listenerList.elements();&nbsp;&nbsp;&nbsp;&nbsp;while ( listeners.hasMoreElements() ) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeModelListener listener = &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(TreeModelListener) listeners.nextElement();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;listener.treeStructureChanged( e );&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;}</code>} // DomToTreeModelAdapter<a name="wp64448"> </a></pre></div><hr><a name="wp64449"> </a><p class="pNote">Note: These methods are taken from the <code class="cCode">TreeModelSupport</code> class described in Understanding the TreeModel. That architecture was produced by Tom Santos and Steve Wilson, and is a lot more elegant than the quick hack going on here. It seemed worthwhile to put them here, though, so they would be immediately at hand when and if they're needed. </p><hr><a name="wp64451"> </a><h3 class="pHeading2">Finishing Up </h3><a name="wp64452"> </a><p class="pBody">At this point, you are basically done. All you need to do is jump back to the constructor and add the code to construct an adapter and deliver it to the <code class="cCode">JTree</code> as the <code class="cCode">TreeModel</code>:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">// Set up the treeJTree tree = new JTree(<code class="cCodeBold">new DomToTreeModelAdapter()</code>); <a name="wp64453"> </a></pre></div><a name="wp64454"> </a><p class="pBody">You can now compile and run the code on an XML file. In the next section, you will do that, and explore the DOM structures that result. </p>    </blockquote>   <img src="images/blueline.gif" width="550" height="8" ALIGN="BOTTOM" NATURALSIZEFLAG="3" ALT="Divider">    <table width="550" summary="layout" id="SummaryNotReq1">      <tr>	<td align="left" valign="center">	<font size="-1">	<a href="http://java.sun.com/j2ee/1.4/download.html#tutorial" target="_blank">Download</a>	<br>	<a href="http://java.sun.com/j2ee/1.4/docs/tutorial/information/faq.html" target="_blank">FAQ</a>	<br>	<a href="http://java.sun.com/j2ee/1.4/docs/tutorial/information/history.html" target="_blank">History</a>	</td>        <td align="center" valign="center"><a accesskey="p" href="JAXPDOM3.html"><img id="LongDescNotReq1" src="images/PrevArrow.gif" width="26" height="26" border="0" alt="Prev" /></a><a accesskey="c" href="J2EETutorialFront.html"><img id="LongDescNotReq1" src="images/UpArrow.gif" width="26" height="26" border="0" alt="Home" /></a><a accesskey="n" href="JAXPDOM5.html"><img id="LongDescNotReq3" src="images/NextArrow.gif" width="26" height="26" border="0" alt="Next" /></a><a accesskey="i" href="J2EETutorialIX.html"></a>        </td>	<td align="right" valign="center">	<font size="-1">	<a href="http://java.sun.com/j2ee/1.4/docs/api/index.html" target="_blank">API</a>	<br>	<a href="http://java.sun.com/j2ee/1.4/docs/tutorial/information/search.html" target="_blank">Search</a>	<br>	<a href="http://java.sun.com/j2ee/1.4/docs/tutorial/information/sendusmail.html" target="_blank">Feedback</a></font>	</font>	</td>      </tr>    </table>    <img src="images/blueline.gif" width="550" height="8" ALIGN="BOTTOM" NATURALSIZEFLAG="3" ALT="Divider"><p><font size="-1">All of the material in <em>The J2EE(TM) 1.4 Tutorial</em> is <a href="J2EETutorialFront2.html">copyright</a>-protected and may not be published in other workswithout express written permission from Sun Microsystems.</font>  </body></html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -