📄 jaxpdom6.html
字号:
There's nothing special going on here. It's a slightly modified version the same logic you used when returning the child count.</p><a name="wp64759"> </a><h4 class="pHeading3">Check the Results</h4><a name="wp64760"> </a><p class="pBody">When you compile and run this version of the application on <code class="cCode">slideSample01.xml</code>, and then expand the nodes in the tree, you see the results shown in <a href="JAXPDOM6.html#wp64769">Figure 6-8</a>. The only nodes remaining in the tree are the high-level "structure" nodes. </p><a name="wp64767"> </a><p class="pBody"></p><div align="left"><img src="images/pd-301a7.gif" height="240" width="378" alt="Tree View with a Collapsed Hierarchy" border="0" hspace="0" vspace="0"/></div><p class="pBody"></p><p> <a name="64769"> </a><strong><font >Figure 6-8 Tree View with a Collapsed Hierarchy</font></strong></p><a name="wp64771"> </a><h4 class="pHeading3">Extra Credit</h4><a name="wp64772"> </a><p class="pBody">The way the application stands now, the information that tells the application how to compress the tree for display is "hard-coded". Here are some ways you could consider extending the app:</p><a name="wp64773"> </a><p class="pDefinitionTerm">Use a Command-Line Argument</p><a name="wp64774"> </a><p class="pDefinition">Whether you compress or don't compress the tree could be determined by a command line argument, rather than being a hard-coded boolean variable. On the other hand, the list the list of elements that goes into the tree is still hard coded, so maybe that option doesn't make much sense, unless...</p><a name="wp64775"> </a><p class="pDefinitionTerm">Read the treeElement list from a file</p><a name="wp64776"> </a><p class="pDefinition">If you read the list of elements to include in the tree from an external file, that would make the whole application command driven. That would be good. But wouldn't it be really nice to derive that information from the DTD or schema, instead? So you might want to consider...</p><a name="wp64777"> </a><p class="pDefinitionTerm">Automatically Build the List </p><a name="wp64778"> </a><p class="pDefinition">Watch out, though! As things stand right now, there are no standard DTD parsers! If you use a DTD, then, you'll need to write your parser to make sense out of its somewhat arcane syntax. You'll probably have better luck if you use a schema, instead of a DTD. The nice thing about schemas is that use XML syntax, so you can use an XML parser to read the schema the same way you use any other file.</p><a name="wp64779"> </a><p class="pDefinition">As you analyze the schema, note that the <code class="cCode">JTree</code>-displayable <span style="font-style: italic">structure</span> nodes are those that have no text, while the <span style="font-style: italic">content</span> nodes may contain text and, optionally, XHTML subnodes. That distinction works for this example, and will likely work for a large body of real-world applications. It's pretty easy to construct cases that will create a problem, though, so you'll have to be on the lookout for schema/DTD specifications that embed non-XHTML elements in text-capable nodes, and take the appropriate action.</p><a name="wp64781"> </a><h3 class="pHeading2">Acting on Tree Selections </h3><a name="wp64782"> </a><p class="pBody">Now that the tree is being displayed properly, the next step is to concatenate the subtrees under selected nodes to display them in the <code class="cCode">htmlPane</code>. While you're at it, you'll use the concatenated text to put node-identifying information back in the <code class="cCode">JTree</code>. </p><hr><a name="wp64783"> </a><p class="pNote">Note: The code discussed in this section is in <code class="cCode"><a href="../examples/jaxp/dom/samples/DomEcho04.java" target="_blank">DomEcho04.java</a></code>.</p><hr><a name="wp64785"> </a><h4 class="pHeading3">Identify Node Types</h4><a name="wp64786"> </a><p class="pBody">When you concatenate the subnodes under an element, the processing you do is going to depend on the type of node. So the first thing to is to define constants for the remaining node types. Add the code highlighted below to do that:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">public class DomEcho extends JPanel{ ... // An array of names for DOM node-types static final String[] typeName = { ... }; static final int ELEMENT_TYPE = 1;<code class="cCodeBold"> static final int ATTR_TYPE = Node.ATTRIBUTE_NODE; static final int TEXT_TYPE = Node.TEXT_NODE; static final int CDATA_TYPE = Node.CDATA_SECTION_NODE; static final int ENTITYREF_TYPE = Node.ENTITY_REFERENCE_NODE; static final int ENTITY_TYPE = Node.ENTITY_NODE; static final int PROCINSTR_TYPE = Node.PROCESSING_INSTRUCTION_NODE; static final int COMMENT_TYPE = Node.COMMENT_NODE; static final int DOCUMENT_TYPE = Node.DOCUMENT_NODE; static final int DOCTYPE_TYPE = Node.DOCUMENT_TYPE_NODE; static final int DOCFRAG_TYPE = Node.DOCUMENT_FRAGMENT_NODE; static final int NOTATION_TYPE = Node.NOTATION_NODE;</code><a name="wp73577"> </a></pre></div><a name="wp64789"> </a><h4 class="pHeading3">Concatenate Subnodes to Define Element Content</h4><a name="wp64790"> </a><p class="pBody">Next, you need to define add the method that concatenates the text and subnodes for an element and returns it as the element's "content". To define the <code class="cCode">content</code> 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><div class="pPreformattedRelative"><pre class="pPreformattedRelative">public class DomEcho extends JPanel{ ... public class AdapterNode { ... public String toString() { ... }<code class="cCodeBold"> public String content() { String s = ""; org.w3c.dom.NodeList nodeList = domNode.getChildNodes(); for (int i=0; i<nodeList.getLength(); i++) { org.w3c.dom.Node node = nodeList.item(i); int type = node.getNodeType(); AdapterNode adpNode = new AdapterNode(node); if (type == ELEMENT_TYPE) { if ( treeElement(node.getNodeName()) ) continue; s += "<" + node.getNodeName() + ">"; s += adpNode.content(); s += "</" + node.getNodeName() + ">"; } else if (type == TEXT_TYPE) { s += node.getNodeValue(); } else if (type == ENTITYREF_TYPE) { // The content is in the TEXT node under it s += adpNode.content(); } else if (type == CDATA_TYPE) { StringBuffer sb = new StringBuffer( node.getNodeValue() ); for (int j=0; j<sb.length(); j++) { if (sb.charAt(j) == '<') { sb.setCharAt(j, '&'); sb.insert(j+1, "lt;"); j += 3; } else if (sb.charAt(j) == '&') { sb.setCharAt(j, '&'); sb.insert(j+1, "amp;"); j += 4; } } s += "<pre>" + sb + "</pre>"; } } return s; }</code> ...} // AdapterNode<a name="wp64791"> </a></pre></div><hr><a name="wp67090"> </a><p class="pNote">Note: This code collapses EntityRef nodes, as inserted by the JAXP 1.1 parser that ins included in the 1.4 Java platform. With JAXP 1.2, that portion of the code is not necessary because entity references are converted to text nodes by the parser. Other parsers may well insert such nodes, however, so including this code "future proofs" your application, should you use a different parser in the future.</p><hr><a name="wp64792"> </a><p class="pBody">Although this code is not the most efficient that anyone ever wrote, it works and it will do fine for our purposes. In this code, you are recognizing and dealing with the following data types:</p><a name="wp64793"> </a><p class="pDefinitionTerm">Element</p><a name="wp64794"> </a><p class="pDefinition">For elements with names like the XHTML "em" node, you return the node's content sandwiched between the appropriate <code class="cCode"><em></code> and <code class="cCode"></em></code> tags. However, when processing the content for the <code class="cCode">slideshow</code> element, for example, you don't include tags for the <code class="cCode">slide</code> elements it contains so, when returning a node's content, you skip any subelements that are themselves displayed in the tree.</p><a name="wp64795"> </a><p class="pDefinitionTerm">Text</p><a name="wp64796"> </a><p class="pDefinition">No surprise here. For a text node, you simply return the node's <code class="cCode">value</code>.</p><a name="wp64797"> </a><p class="pDefinitionTerm">Entity Reference</p><a name="wp64798"> </a><p class="pDefinition">Unlike <code class="cCode">CDATA</code> nodes, Entity References can contain multiple subelements. So the strategy here is to return the concatenation of those subelements.</p><a name="wp64799"> </a><p class="pDefinitionTerm">CDATA</p><a name="wp64800"> </a><p class="pDefinition">Like a text node, you return the node's <code class="cCode">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 <code class="cCode"><pre></code> tag does not prevent the parsing of character-format tags, break tags and the like. So you have to convert left-angle brackets (<code class="cCode"><</code>) and ampersands (<code class="cCode">&</code>) to get them to display properly.</p><a name="wp64801"> </a><p class="pBody">On the other hand, there are quite a few node types you are <span style="font-style: italic">not</span> processing with the code above. It's worth a moment to examine them and understand why:</p><a name="wp64802"> </a><p class="pDefinitionTerm">Attribute</p><a name="wp64803"> </a><p class="pDefinition">These nodes do not appear in the DOM, but are obtained by invoking <code class="cCode">getAttributes</code> on element nodes.</p><a name="wp64804"> </a><p class="pDefinitionTerm">Entity </p><a name="wp64805"> </a><p class="pDefinition">These nodes also do not appear in the DOM. They are obtained by invoking <code class="cCode">getEntities</code> on <code class="cCode">DocType</code> nodes.</p><a name="wp64806"> </a><p class="pDefinitionTerm">Processing Instruction</p><a name="wp64807"> </a><p class="pDefinition">These nodes don't contain displayable data.</p><a name="wp64808"> </a><p class="pDefinitionTerm">Comment </p><a name="wp64809"> </a><p class="pDefinition">Ditto. Nothing you want to display here.</p><a name="wp64810"> </a><p class="pDefinitionTerm">Document</p><a name="wp64811"> </a><p class="pDefinition">This is the root node for the DOM. There's no data to display for that.</p><a name="wp64812"> </a><p class="pDefinitionTerm">DocType</p><a name="wp64813"> </a><p class="pDefinition">The <code class="cCode">DocType</code> 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.</p><a name="wp64814"> </a><p class="pDefinitionTerm">Document Fragment</p><a name="wp64815"> </a><p class="pDefinition">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.</p><a name="wp64816"> </a><p class="pDefinitionTerm">Notation
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -