本例使用的是XMLBean2.2。读者需要saxon8.xml, saxon8-dom.xml, xbean_xpath.jar来运行本例。 这些jar包都包含在了XMLBean2.2下载包中。
XMLBean功能强大,因此不可能在这里详细阐述。读者可以访问 XMLBean主页。在这里我只是针对XMLBean中XMLObject和XMLCursor类在XPath和XQuery中的应用给出一些实例。
XMLObject接口对应于一个XML文档中的 xs:anyType类型。XMLObject是所有XMLBean类的基础类。
XMLCursor接口在使用上类似JDBC中的SQL Cursor,对当前文档创建了一个指针。用户就可以基于指针的位置进行数据的处理和对文挡中的元素进行搜索。因为是接口,所以用户不能直接生成XMLCursor实例。用户需要调用当前XMLObject的newCursor()方法来创建针对该XMLObject的XMLCursor实例。
下面给出的例子使用XMLObject和XMLCursor编写了一个对XML文件做XPath处理的工具:
主要方法:
parseXml() - 将xml文档转化为xmlObject实例
getXpathValue() - 获取单个XPath的文本值,Xpath如果返回多个值则取第一个
getXpathValues() - 获取所有XPath的文本值,返回值放入数组中.
getXpathElement() - 获取单个XPath的元素对象,Xpath如果返回多个值则取第一个
getXpathElements() - 获取所有XPath的元素对象,返回值放入数组中.
setXpathValue() - 修改单个XPath位置的值,Xpath如果返回多个值则取第一个
<span style="font-size:18px;">package com.agilelogicsolutions.util;
import org.apache.xmlbeans.XmlCursor;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlObject;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Formatter;
import java.util.List;
public class CursorHelper {
static boolean verbose = false;
public CursorHelper() {
}
/**
* Parses the XML File
*
* @param xmlFilePath
* @return
*/
public XmlObject parseXml(String xmlFilePath) {
File xmlFile = new File(xmlFilePath);
XmlObject xml = null;
try {
xml = XmlObject.Factory.parse(xmlFile);
} catch (XmlException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return xml;
}
public XmlObject parseXml(InputStream is) {
XmlObject xml = null;
try {
xml = XmlObject.Factory.parse(is);
} catch (XmlException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return xml;
}
/**
* Used to get the value from a specific XPath in the namespace
*
* @param xml
* @param nameSpace
* @param xpath
* @return
*/
public String getXPathValue(XmlObject xml, String nameSpace, String xpath) {
// Create a temporary cursor for the XPath passed in
XmlCursor xpathCursor = xml.newCursor();
// Create a formatter to format the XPath
StringBuilder builder = new StringBuilder();
Formatter formatter = new Formatter(builder);
formatter.format("%s %s", nameSpace, xpath);
// Select the XPath
xpathCursor.selectPath(formatter.toString());
xpathCursor.toNextSelection();
// Using ternary operation - if selection count >0 then return the value
// else return null
String pathValue = xpathCursor.getSelectionCount() > 0 ? xpathCursor
.getTextValue() : null;
// We don't need the cursor any more... dispose of it
xpathCursor.dispose();
// Logging
if (verbose) {
builder = new StringBuilder();
Formatter msgFormatter = new Formatter(builder);
System.out.println(msgFormatter.format(
"Value %-35s XPath expression: %s %s", pathValue,
nameSpace, xpath));
}
return pathValue;
}
/**
* Used to get the value from a specific XPath in the namespace
*
* @param xml
* @param nameSpace
* @param xpath
* @return
*/
public String[] getXPathValues(XmlObject xml, String nameSpace, String xpath) {
// Create a temporary cursor for the XPath passed in
XmlCursor xpathCursor = xml.newCursor();
List<String> pathValues = new ArrayList<String>();
// Create a formatter to format the XPath
StringBuilder builder = new StringBuilder();
Formatter formatter = new Formatter(builder);
formatter.format("%s %s", nameSpace, xpath);
// Select the XPath
xpathCursor.selectPath(formatter.toString());
while (xpathCursor.toNextSelection()) {
// Using ternary operation - if selection count >0 then return the value
// else return null
pathValues.add(xpathCursor.getSelectionCount() > 0 ? xpathCursor.getTextValue() : null);
}
// We don't need the cursor any more... dispose of it
xpathCursor.dispose();
// Logging
if (verbose) {
builder = new StringBuilder();
Formatter msgFormatter = new Formatter(builder);
System.out.println(msgFormatter.format(
"Value %-35s XPath expression: %s %s", pathValues.toString(),
nameSpace, xpath));
}
return pathValues.toArray(new String[pathValues.size()]);
}
/**
* Used to get the whole element from a specific XPath in the namespace
*
* @param xml
* @param nameSpace
* @param xpath
* @return
*/
public XmlObject getXPathElement(XmlObject xml, String nameSpace, String xpath) {
// Create a temporary cursor for the XPath passed in
XmlCursor xpathCursor = xml.newCursor();
// Create a formatter to format the XPath
StringBuilder builder = new StringBuilder();
Formatter formatter = new Formatter(builder);
formatter.format("%s %s", nameSpace, xpath);
// Select the XPath
xpathCursor.selectPath(formatter.toString());
xpathCursor.toNextSelection();
// Using ternary operation - if selection count >0 then return the value
// else return null
XmlObject pathElement = xpathCursor.getSelectionCount() > 0 ? xpathCursor.getObject() : null;
// We don't need the cursor any more... dispose of it
xpathCursor.dispose();
// Logging
if (verbose) {
builder = new StringBuilder();
Formatter msgFormatter = new Formatter(builder);
System.out.println(msgFormatter.format(
"Value %-35s XPath expression: %s %s", pathElement.toString(),
nameSpace, xpath));
}
return pathElement;
}
/**
* Used to get the whole element from a specific XPath in the namespace
*
* @param xml
* @param nameSpace
* @param xpath
* @return
*/
public XmlObject[] getXPathElements(XmlObject xml, String nameSpace, String xpath) {
// Create a temporary cursor for the XPath passed in
XmlCursor xpathCursor = xml.newCursor();
List<XmlObject> pathElements = new ArrayList<XmlObject>();
// Create a formatter to format the XPath
StringBuilder builder = new StringBuilder();
Formatter formatter = new Formatter(builder);
formatter.format("%s %s", nameSpace, xpath);
// Select the XPath
xpathCursor.selectPath(formatter.toString());
while (xpathCursor.toNextSelection()) {
// Using ternary operation - if selection count >0 then return the value
// else return null
pathElements.add(xpathCursor.getSelectionCount() > 0 ? xpathCursor.getObject() : null);
}
// We don't need the cursor any more... dispose of it
xpathCursor.dispose();
// Logging
if (verbose) {
builder = new StringBuilder();
Formatter msgFormatter = new Formatter(builder);
System.out.println(msgFormatter.format(
"Value %-35s XPath expression: %s %s", pathElements.toString(),
nameSpace, xpath));
}
return pathElements.toArray(new XmlObject[pathElements.size()]);
}
/**
* Used to set the value to a specific XPath in the namespace
*
* @param xml
* @param nameSpace
* @param xpath
* @param value
* @return
*/
public XmlObject setXPathValue(XmlObject xml, String nameSpace, String xpath, String value) {
// Create a temporary cursor for the XPath passed in
XmlCursor xpathCursor = xml.newCursor();
// Create a formatter to format the XPath
StringBuilder builder = new StringBuilder();
Formatter formatter = new Formatter(builder);
formatter.format("%s %s", nameSpace, xpath);
// Select the XPath
xpathCursor.selectPath(formatter.toString());
xpathCursor.toNextSelection();
// Using ternary operation - if selection count >0 then return the value
// else return null
if (xpathCursor.getSelectionCount() > 0)
xpathCursor.setTextValue(value);
// We don't need the cursor any more... dispose of it
xpathCursor.dispose();
// Logging
if (verbose) {
builder = new StringBuilder();
Formatter msgFormatter = new Formatter(builder);
System.out.println(msgFormatter.format(
"XPath value at %s %s is updated to: %s", nameSpace, xpath, value));
}
return xml;
}
public static void main(String[] args) {
CursorHelper cursor = new CursorHelper();
XmlObject xml = cursor.parseXml("C:/My_Dir/mySample.xml");
String value = cursor.getXPathValue(xml,
"declare namespace s11='http://schemas.xmlsoap.org/soap/envelope/'; ",
"$this/s11:Envelope/s11:Body/*/s11:ResponseHeader/s11:Status/s11:StatusCode");
System.out.println("Value is: " + value);
}
}
</span>
上例主要使用了XMLCursor中的selectPath()方法来实现XPath调用。使用selectPath()后,程序并不返回当前位置的值,只是把指针移动到指定的XPath位置。然后通过toNextSelection()方法选定要返回的XML元素,最后使用getObject()或者getTextValue()方法返回XML对象或是文本值。类似的,对于XQuery调用,则使用executeQuery()方法。executeQuery()返回一个包含XQuery结果的XMLCurosr指针。值得注意的是XMLBean对命名空间的要求。所有XPath和XQuery请求都需要给出相应的命名空间。可以参考上例中的main()方法查看如何实现一个具体的XPath请求
通过XMLCursor,用户可以轻松访问XML文档,对内容进行查询和修改。