|
If you want to locate a specific piece of information in an XML document, then it can be a bit of a hassle to navigate the nodes of the DOM tree. The XPath language makes it simple to access tree nodes. For example, suppose you have this XML document: <configuration> . . . <database> <username>dbuser</username> <password>secret</password> . . . </database> </configuration> You can get the database user name by evaluating the XPath expression /configuration/database/username That's a lot simpler than the plain DOM approach:
An XPath can describe a set of nodes in an XML document. For example, the XPath /gridbag/row describes the set of all row elements that are children of the gridbag root element. You can select a particular element with the [] operator: /gridbag/row[1] is the first row. (The index values start at 1.) Use the @ operator to get attribute values. The XPath expression /gridbag/row[1]/cell[1]/@anchor describes the anchor attribute of the first cell in the first row. The XPath expression /gridbag/row/cell/@anchor describes all anchor attribute nodes of cell elements within row elements that are children of the gridbag root node. There are a number of useful XPath functions. For example, count(/gridbag/row) returns the number of row children of the gridbag root. There are many more elaborate XPath expressionssee the specification at http://www.w3c.org/TR/xpath or the nifty online tutorial at http://www.zvon.org/xxl/XPathTutorial/General/examples.html. JDK 5.0 adds an API to evaluate XPath expressions. You first create an XPath object from an XPathFactory: XPathFactory xpfactory = XPathFactory.newInstance(); path = xpfactory.newXPath(); You then call the evaluate method to evaluate XPath expressions: String username = path.evaluate("/configuration/database/username", doc); You can use the same XPath object to evaluate multiple expressions. This form of the evaluate method returns a string result. It is suitable for retrieving text, such as the text of the username node in the preceding example. If an XPath expression yields a node set, make a call such as the following: NodeList nodes = (NodeList) path.evaluate("/gridbag/row", doc, XPathConstants.NODESET); If the result is a single node, use XPathConstants.NODE instead: Node node = (Node) path.evaluate("/gridbag/row[1]", doc, XPathConstants.NODE); If the result is a number, use XPathConstants.NUMBER:
You don't have to start the search at the document root. You can start the search at any node or node list. For example, if you have a node from a previous evaluation, you can call result = path.evaluate(expression, node); The program in Example 12-7 demonstrates the evaluation of XPath expressions. Load an XML file and type an expression. Select the expression type and click the Evaluate button. The result of the expression is displayed at the bottom of the frame (see Figure 12-5). Example 12-7. XPathTest.java[View full width] 1. import java.awt.*; 2. import java.awt.event.*; 3. import java.io.*; 4. import javax.swing.*; 5. import javax.swing.border.*; 6. import javax.xml.namespace.*; 7. import javax.xml.parsers.*; 8. import javax.xml.xpath.*; 9. import org.w3c.dom.*; 10. import org.xml.sax.*; 11. 12. /** 13. This program evaluates XPath expressions 14. */ 15. public class XPathTest 16. { 17. public static void main(String[] args) 18. { 19. JFrame frame = new XPathFrame(); 20. frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 21. frame.setVisible(true); 22. } 23. } 24. 25. /** 26. This frame shows an XML document, a panel to type an XPath expression, 27. and a text field to display the result. 28. */ 29. class XPathFrame extends JFrame 30. { 31. public XPathFrame() 32. { 33. setTitle("XPathTest"); 34. 35. JMenu fileMenu = new JMenu("File"); 36. JMenuItem openItem = new JMenuItem("Open"); 37. openItem.addActionListener(new 38. ActionListener() 39. { 40. public void actionPerformed(ActionEvent event) { openFile(); } 41. }); 42. fileMenu.add(openItem); 43. 44. JMenuItem exitItem = new JMenuItem("Exit"); 45. exitItem.addActionListener(new 46. ActionListener() 47. { 48. public void actionPerformed(ActionEvent event) { System.exit(0); } 49. }); 50. fileMenu.add(exitItem); 51. 52. JMenuBar menuBar = new JMenuBar(); 53. menuBar.add(fileMenu); 54. setJMenuBar(menuBar); 55. 56. ActionListener listener = new 57. ActionListener() 58. { 59. public void actionPerformed(ActionEvent event) { evaluate(); } 60. }; 61. expression = new JTextField(20); 62. expression.addActionListener(listener); 63. JButton evaluateButton = new JButton("Evaluate"); 64. evaluateButton.addActionListener(listener); 65. 66. typeCombo = new JComboBox(new Object[] { "STRING", "NODE", "NODESET", "NUMBER", "BOOLEAN" }); 67. typeCombo.setSelectedItem("STRING"); 68. 69. JPanel panel = new JPanel(); 70. panel.add(expression); 71. panel.add(typeCombo); 72. panel.add(evaluateButton); 73. docText = new JTextArea(10, 40); 74. result = new JTextField(); 75. result.setBorder(new TitledBorder("Result")); 76. 77. add(panel, BorderLayout.NORTH); 78. add(new JScrollPane(docText), BorderLayout.CENTER); 79. add(result, BorderLayout.SOUTH); 80. 81. try 82. { 83. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 84. builder = factory.newDocumentBuilder(); 85. } 86. catch (ParserConfigurationException e) 87. { 88. JOptionPane.showMessageDialog(this, e); 89. } 90. 91. XPathFactory xpfactory = XPathFactory.newInstance(); 92. path = xpfactory.newXPath(); 93. pack(); 94. } 95. 96. /** 97. Open a file and load the document. 98. */ 99. public void openFile() 100. { 101. JFileChooser chooser = new JFileChooser(); 102. chooser.setCurrentDirectory(new File(".")); 103. 104. chooser.setFileFilter(new 105. javax.swing.filechooser.FileFilter() 106. { 107. public boolean accept(File f) 108. { 109. return f.isDirectory() || f.getName().toLowerCase().endsWith(".xml"); 110. } 111. public String getDescription() { return "XML files"; } 112. }); 113. int r = chooser.showOpenDialog(this); 114. if (r != JFileChooser.APPROVE_OPTION) return; 115. File f = chooser.getSelectedFile(); 116. try 117. { 118. byte[] bytes = new byte[(int) f.length()]; 119. new FileInputStream(f).read(bytes); 120. docText.setText(new String(bytes)); 121. doc = builder.parse(f); 122. } 123. catch (IOException e) 124. { 125. JOptionPane.showMessageDialog(this, e); 126. } 127. catch (SAXException e) 128. { 129. JOptionPane.showMessageDialog(this, e); 130. } 131. } 132. 133. public void evaluate() 134. { 135. 136. try 137. { 138. String typeName = (String) typeCombo.getSelectedItem(); 139. QName returnType = (QName) XPathConstants.class.getField(typeName).get(null); 140. Object evalResult = path.evaluate(expression.getText(), doc, returnType); 141. if (typeName.equals("NODESET")) 142. { 143. NodeList list = (NodeList) evalResult; 144. StringBuilder builder = new StringBuilder(); 145. builder.append("{"); 146. for (int i = 0; i < list.getLength(); i++) 147. { 148. if (i > 0) builder.append(", "); 149. builder.append("" + list.item(i)); 150. } 151. builder.append("}"); 152. result.setText("" + builder); 153. } 154. else 155. result.setText("" + evalResult); 156. } 157. catch (XPathExpressionException e) 158. { 159. result.setText("" + e); 160. } 161. catch (Exception e) // reflection exception 162. { 163. e.printStackTrace(); 164. } 165. } 166. 167. private DocumentBuilder builder; 168. private Document doc; 169. private XPath path; 170. private JTextField expression; 171. private JTextField result; 172. private JTextArea docText; 173. private JComboBox typeCombo; 174. } Figure 12-5. Evaluating XPath expressions javax.xml.xpath.XPathFactory 5.0
javax.xml.xpath.XPath 5.0
|
|