java 解析xml的更好方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15626686/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Better way to parse xml
提问by Gandalf StormCrow
I've been parsing XML like this for years, and I have to admit when the number of different element becomes larger I find it a bit boring and exhausting to do, here is what I mean, sample dummy XML:
我已经像这样解析 XML 多年了,我不得不承认,当不同元素的数量变大时,我觉得这样做有点无聊和筋疲力尽,这就是我的意思,示例虚拟 XML:
<?xml version="1.0"?>
<Order>
<Date>2003/07/04</Date>
<CustomerId>123</CustomerId>
<CustomerName>Acme Alpha</CustomerName>
<Item>
<ItemId> 987</ItemId>
<ItemName>Coupler</ItemName>
<Quantity>5</Quantity>
</Item>
<Item>
<ItemId>654</ItemId>
<ItemName>Connector</ItemName>
<Quantity unit="12">3</Quantity>
</Item>
<Item>
<ItemId>579</ItemId>
<ItemName>Clasp</ItemName>
<Quantity>1</Quantity>
</Item>
</Order>
This is relevant part (using sax) :
这是相关部分(使用 sax):
public class SaxParser extends DefaultHandler {
boolean isItem = false;
boolean isOrder = false;
boolean isDate = false;
boolean isCustomerId = false;
private Order order;
private Item item;
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
if (localName.equalsIgnoreCase("ORDER")) {
order = new Order();
}
if (localName.equalsIgnoreCase("DATE")) {
isDate = true;
}
if (localName.equalsIgnoreCase("CUSTOMERID")) {
isCustomerId = true;
}
if (localName.equalsIgnoreCase("ITEM")) {
isItem = true;
}
}
public void characters(char ch[], int start, int length) throws SAXException {
if (isDate){
SimpleDateFormat formatter = new SimpleDateFormat("yyyy/MM/dd");
String value = new String(ch, start, length);
try {
order.setDate(formatter.parse(value));
} catch (ParseException e) {
e.printStackTrace();
}
}
if(isCustomerId){
order.setCustomerId(Integer.valueOf(new String(ch, start, length)));
}
if (isItem) {
item = new Item();
isItem = false;
}
}
}
I'm wondering is there a way to get rid of these hideous booleans which keep growing with number of elements. There must be a better way to parse this relatively simple xml. Just by looking the lines of code necessary to do this task looks ugly.
我想知道有没有办法摆脱这些随着元素数量不断增长的可怕布尔值。一定有更好的方法来解析这个相对简单的xml。仅通过查看执行此任务所需的代码行看起来很难看。
Currently I'm using SAX parser, but I'm open to any other suggestions (other than DOM, I can't afford in memory parsers I have huge XML files).
目前我正在使用 SAX 解析器,但我愿意接受任何其他建议(除了 DOM,我无法负担内存解析器的巨大 XML 文件)。
采纳答案by Sami Korhonen
Here's an example of using JAXB with StAX.
这是将 JAXB 与 StAX 结合使用的示例。
Input document:
输入文件:
<?xml version="1.0" encoding="UTF-8"?>
<Personlist xmlns="http://example.org">
<Person>
<Name>Name 1</Name>
<Address>
<StreetAddress>Somestreet</StreetAddress>
<PostalCode>00001</PostalCode>
<CountryName>Finland</CountryName>
</Address>
</Person>
<Person>
<Name>Name 2</Name>
<Address>
<StreetAddress>Someotherstreet</StreetAddress>
<PostalCode>43400</PostalCode>
<CountryName>Sweden</CountryName>
</Address>
</Person>
</Personlist>
Person.java:
人.java:
@XmlRootElement(name = "Person", namespace = "http://example.org")
public class Person {
@XmlElement(name = "Name", namespace = "http://example.org")
private String name;
@XmlElement(name = "Address", namespace = "http://example.org")
private Address address;
public String getName() {
return name;
}
public Address getAddress() {
return address;
}
}
Address.java:
地址.java:
public class Address {
@XmlElement(name = "StreetAddress", namespace = "http://example.org")
private String streetAddress;
@XmlElement(name = "PostalCode", namespace = "http://example.org")
private String postalCode;
@XmlElement(name = "CountryName", namespace = "http://example.org")
private String countryName;
public String getStreetAddress() {
return streetAddress;
}
public String getPostalCode() {
return postalCode;
}
public String getCountryName() {
return countryName;
}
}
PersonlistProcessor.java:
PersonlistProcessor.java:
public class PersonlistProcessor {
public static void main(String[] args) throws Exception {
new PersonlistProcessor().processPersonlist(PersonlistProcessor.class
.getResourceAsStream("personlist.xml"));
}
// TODO: Instead of throws Exception, all exceptions should be wrapped
// inside runtime exception
public void processPersonlist(InputStream inputStream) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(Person.class);
XMLStreamReader xss = XMLInputFactory.newFactory().createXMLStreamReader(inputStream);
// Create unmarshaller
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
// Go to next tag
xss.nextTag();
// Require Personlist
xss.require(XMLStreamReader.START_ELEMENT, "http://example.org", "Personlist");
// Go to next tag
while (xss.nextTag() == XMLStreamReader.START_ELEMENT) {
// Require Person
xss.require(XMLStreamReader.START_ELEMENT, "http://example.org", "Person");
// Unmarshall person
Person person = (Person)unmarshaller.unmarshal(xss);
// Process person
processPerson(person);
}
// Require Personlist
xss.require(XMLStreamReader.END_ELEMENT, "http://example.org", "Personlist");
}
private void processPerson(Person person) {
System.out.println(person.getName());
System.out.println(person.getAddress().getCountryName());
}
}
回答by Marcelo
If you control the definition of the XML, you could use an XML binding tool, for example JAXB(Java Architecture for XML Binding.) In JAXB you can define a schema for the XML structure (XSD and others are supported) or annotate your Java classes in order to define the serialization rules. Once you have a clear declarative mapping between XML and Java, marshalling and unmarshalling to/from XML becomes trivial.
如果您控制 XML 的定义,则可以使用 XML 绑定工具,例如JAXB(XML 绑定的 Java 架构)。在 JAXB 中,您可以为 XML 结构定义模式(支持 XSD 和其他)或注释您的 Java类以定义序列化规则。一旦在 XML 和 Java 之间有了清晰的声明性映射,在 XML 之间进行编组和解组就变得微不足道了。
Using JAXB does require more memory than SAX handlers, but there exist methods to process the XML documents by parts: Dealing with large documents.
回答by Trade-Ideas Philip
I've been using this library. It sits on top of the standard Java library and makes things easier for me. In particular, you can ask for a specific element or attribute by name, rather than using the big "if" statement you've described.
我一直在使用这个库。它位于标准 Java 库之上,让我的工作更轻松。特别是,您可以按名称请求特定元素或属性,而不是使用您所描述的大“if”语句。
http://marketmovers.blogspot.com/2014/02/the-easy-way-to-read-xml-in-java.html
http://marketmovers.blogspot.com/2014/02/the-easy-way-to-read-xml-in-java.html
回答by Pythagoras
There is another library which supports more compact XML parsing, RTXML. The library and its documentation is on rasmustorkel.com. I implemented the parsing of the file in the original question and I am including the complete program here:
还有另一个支持更紧凑的 XML 解析的库,RTXML。该库及其文档位于rasmustorkel.com 上。我在原始问题中实现了文件的解析,我在这里包含了完整的程序:
package for_so;
import java.io.File;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import rasmus_torkel.xml_basic.read.TagNode;
import rasmus_torkel.xml_basic.read.XmlReadOptions;
import rasmus_torkel.xml_basic.read.impl.XmlReader;
public class Q15626686_ReadOrder
{
public static class Order
{
public final Date _date;
public final int _customerId;
public final String _customerName;
public final ArrayList<Item> _itemAl;
public
Order(TagNode node)
{
_date = (Date)node.nextStringMappedFieldE("Date", Date.class);
_customerId = (int)node.nextIntFieldE("CustomerId");
_customerName = node.nextTextFieldE("CustomerName");
_itemAl = new ArrayList<Item>();
boolean finished = false;
while (!finished)
{
TagNode itemNode = node.nextChildN("Item");
if (itemNode != null)
{
Item item = new Item(itemNode);
_itemAl.add(item);
}
else
{
finished = true;
}
}
node.verifyNoMoreChildren();
}
}
public static final Pattern DATE_PATTERN = Pattern.compile("^(\d\d\d\d)\/(\d\d)\/(\d\d)$");
public static class Date
{
public final String _dateString;
public final int _year;
public final int _month;
public final int _day;
public
Date(String dateString)
{
_dateString = dateString;
Matcher matcher = DATE_PATTERN.matcher(dateString);
if (!matcher.matches())
{
throw new RuntimeException(dateString + " does not match pattern " + DATE_PATTERN.pattern());
}
_year = Integer.parseInt(matcher.group(1));
_month = Integer.parseInt(matcher.group(2));
_day = Integer.parseInt(matcher.group(3));
}
}
public static class Item
{
public final int _itemId;
public final String _itemName;
public final Quantity _quantity;
public
Item(TagNode node)
{
_itemId = node.nextIntFieldE("ItemId");
_itemName = node.nextTextFieldE("ItemName");
_quantity = new Quantity(node.nextChildE("Quantity"));
node.verifyNoMoreChildren();
}
}
public static class Quantity
{
public final int _unitSize;
public final int _unitQuantity;
public
Quantity(TagNode node)
{
_unitSize = node.attributeIntD("unit", 1);
_unitQuantity = node.onlyInt();
}
}
public static void
main(String[] args)
{
File xmlFile = new File(args[0]);
TagNode orderNode = XmlReader.xmlFileToRoot(xmlFile, "Order", XmlReadOptions.DEFAULT);
Order order = new Order(orderNode);
System.out.println("Read order for " + order._customerName + " which has " + order._itemAl.size() + " items");
}
}
You will notice that the retrieval functions end in N, E or D. They refer to what to do when the desired data item is not there. N stands for return Null, E stands for throw Exception and D stands for use Default.
您会注意到检索函数以 N、E 或 D 结尾。它们指的是当所需数据项不存在时要做什么。N 代表 return Null,E 代表 throw Exception,D 代表使用 Default。
回答by mike rodent
Solution without using outside package, or even XPath:use an enum
"PARSE_MODE", probably in combination with a Stack<PARSE_MODE>
:
不使用外部包或什至 XPath 的解决方案:使用enum
“PARSE_MODE”,可能与Stack<PARSE_MODE>
:
1) The basic solution:
1)基本解决方案:
a) fields
a) 字段
private PARSE_MODE parseMode = PARSE_MODE.__UNDEFINED__;
// NB: essential that all these enum values are upper case, but this is the convention anyway
private enum PARSE_MODE {
__UNDEFINED__, ORDER, DATE, CUSTOMERID, ITEM };
private List<String> parseModeStrings = new ArrayList<String>();
private Stack<PARSE_MODE> modeBreadcrumbs = new Stack<PARSE_MODE>();
b) make your List<String>
, maybe in the constructor:
b) 使您的List<String>
, 可能在构造函数中:
for( PARSE_MODE pm : PARSE_MODE.values() ){
// might want to check here that these are indeed upper case
parseModeStrings.add( pm.name() );
}
c) startElement
and endElement
:
c)startElement
和endElement
:
@Override
public void startElement(String namespaceURI, String localName, String qName, Attributes atts) {
String localNameUC = localName.toUpperCase();
// pushing "__UNDEFINED__" would mess things up! But unlikely name for an XML element
assert ! localNameUC.equals( "__UNDEFINED__" );
if( parseModeStrings.contains( localNameUC )){
parseMode = PARSE_MODE.valueOf( localNameUC );
// any "policing" to do with which modes are allowed to switch into
// other modes could be put here...
// in your case, go `new Order()` here when parseMode == ORDER
modeBreadcrumbs.push( parseMode );
}
else {
// typically ignore the start of this element...
}
}
@Override
private void endElement(String uri, String localName, String qName) throws Exception {
String localNameUC = localName.toUpperCase();
if( parseModeStrings.contains( localNameUC )){
// will not fail unless XML structure which is malformed in some way
// or coding error in use of the Stack, etc.:
assert modeBreadcrumbs.pop() == parseMode;
if( modeBreadcrumbs.empty() ){
parseMode = PARSE_MODE.__UNDEFINED__;
}
else {
parseMode = modeBreadcrumbs.peek();
}
}
else {
// typically ignore the end of this element...
}
}
... so what does this all mean? At any one time you have knowledge of the "parse mode" you're in ... and you can also look at the Stack<PARSE_MODE> modeBreadcrumbs
if you need to find out what other parse modes you passed through to get here...
... 那么,这意味着什么?在任何时候,您都了解您所处的“解析模式”……并且您还可以查看Stack<PARSE_MODE> modeBreadcrumbs
是否需要找出您通过哪些其他解析模式到达这里……
Your characters
method then becomes substantially cleaner:
characters
然后您的方法变得更加清晰:
public void characters(char[] ch, int start, int length) throws SAXException {
switch( parseMode ){
case DATE:
// PS - this SimpleDateFormat object can be a field: it doesn't need to be created hundreds of times
SimpleDateFormat formatter. ...
String value = ...
...
break;
case CUSTOMERID:
order.setCustomerId( ...
break;
case ITEM:
item = new Item();
// this next line probably won't be needed: when you get to endElement, if
// parseMode is ITEM, the previous mode will be restored automatically
// isItem = false ;
}
}
2) The more "professional" solution:abstract
class which concrete classes have to extend and which then have no ability to modify the Stack
, etc. NB this examines qName
rather than localName
. Thus:
2)更“专业”的解决方案:abstract
具体类必须扩展的类,然后无法修改Stack
等。注意,这检查qName
而不是localName
。因此:
public abstract class AbstractSAXHandler extends DefaultHandler {
protected enum PARSE_MODE implements SAXHandlerParseMode {
__UNDEFINED__
};
// abstract: the concrete subclasses must populate...
abstract protected Collection<Enum<?>> getPossibleModes();
//
private Stack<SAXHandlerParseMode> modeBreadcrumbs = new Stack<SAXHandlerParseMode>();
private Collection<Enum<?>> possibleModes;
private Map<String, Enum<?>> nameToEnumMap;
private Map<String, Enum<?>> getNameToEnumMap(){
// lazy creation and population of map
if( nameToEnumMap == null ){
if( possibleModes == null ){
possibleModes = getPossibleModes();
}
nameToEnumMap = new HashMap<String, Enum<?>>();
for( Enum<?> possibleMode : possibleModes ){
nameToEnumMap.put( possibleMode.name(), possibleMode );
}
}
return nameToEnumMap;
}
protected boolean isLegitimateModeName( String name ){
return getNameToEnumMap().containsKey( name );
}
protected SAXHandlerParseMode getParseMode() {
return modeBreadcrumbs.isEmpty()? PARSE_MODE.__UNDEFINED__ : modeBreadcrumbs.peek();
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes)
throws SAXException {
try {
_startElement(uri, localName, qName, attributes);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// override in subclasses (NB I think caught Exceptions are not a brilliant design choice in Java)
protected void _startElement(String uri, String localName, String qName, Attributes attributes)
throws Exception {
String qNameUC = qName.toUpperCase();
// very undesirable ever to push "UNDEFINED"! But unlikely name for an XML element
assert !qNameUC.equals("__UNDEFINED__") : "Encountered XML element with qName \"__UNDEFINED__\"!";
if( getNameToEnumMap().containsKey( qNameUC )){
Enum<?> newMode = getNameToEnumMap().get( qNameUC );
modeBreadcrumbs.push( (SAXHandlerParseMode)newMode );
}
}
@Override
public void endElement(String uri, String localName, String qName) throws SAXException {
try {
_endElement(uri, localName, qName);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
// override in subclasses
protected void _endElement(String uri, String localName, String qName) throws Exception {
String qNameUC = qName.toUpperCase();
if( getNameToEnumMap().containsKey( qNameUC )){
modeBreadcrumbs.pop();
}
}
public List<?> showModeBreadcrumbs(){
return org.apache.commons.collections4.ListUtils.unmodifiableList( modeBreadcrumbs );
}
}
interface SAXHandlerParseMode {
}
Then, salient part of concrete subclass:
然后,具体子类的显着部分:
private enum PARSE_MODE implements SAXHandlerParseMode {
ORDER, DATE, CUSTOMERID, ITEM
};
private Collection<Enum<?>> possibleModes;
@Override
protected Collection<Enum<?>> getPossibleModes() {
// lazy initiation
if (possibleModes == null) {
List<SAXHandlerParseMode> parseModes = new ArrayList<SAXHandlerParseMode>( Arrays.asList(PARSE_MODE.values()) );
possibleModes = new ArrayList<Enum<?>>();
for( SAXHandlerParseMode parseMode : parseModes ){
possibleModes.add( PARSE_MODE.valueOf( parseMode.toString() ));
}
// __UNDEFINED__ mode (from abstract superclass) must be added afterwards
possibleModes.add( AbstractSAXHandler.PARSE_MODE.__UNDEFINED__ );
}
return possibleModes;
}
PS this is a starting point for more sophisticated stuff: for example, you might set up a List<Object>
which is kept synchronised with the Stack<PARSE_MODE>
: the Objects
could then be anything you want, enabling you to "reach back" into the ascendant "XML nodes" of the one you're dealing with. Don't use a Map
, though: the Stack
can potentially contain the same PARSE_MODE
object more than once. This in fact illustrates a fundamental characteristic of all tree-like structures: no individual node(here: parse mode)exists in isolation: its identity is always defined by the entire path leading to it.
PS 这是更复杂的东西的起点:例如,您可以设置一个List<Object>
与Stack<PARSE_MODE>
:保持同步的:Objects
然后可以是您想要的任何东西,使您能够“返回”到上升的“XML 节点”你正在处理的一个。但是,不要使用Map
:Stack
可能会PARSE_MODE
多次包含相同的对象。这实际上说明了所有树状结构的基本特征:没有单独的节点(此处:解析模式)孤立存在:其身份始终由通向它的整个路径定义。
回答by Thorn
I've been using xsteamto serialize my own objects to xml and then load them back as Java objects. If you can represent everythign as POJOs and you properly annotate the POJOs to match the types in your xml file you might find it much easier to use.
我一直在使用xsteam将我自己的对象序列化为 xml,然后将它们作为 Java 对象加载回来。如果您可以将所有内容表示为 POJO,并且您正确地注释 POJO 以匹配您的 xml 文件中的类型,您可能会发现它更易于使用。
When a String represents an object in XML, you can just write:
当 String 代表 XML 中的对象时,您只需编写:
Order theOrder = (Order)xstream.fromXML(xmlString);
Order theOrder = (Order)xstream.fromXML(xmlString);
I have always used it to load an object into memory in a single line, but if you need to stream it and process as you go you should be able to use a HierarchicalStreamReaderto iterate through the document. This might be very similar to Simple, suggested by @Dave.
我一直使用它在一行中将对象加载到内存中,但是如果您需要流式传输它并随时处理,您应该能够使用HierarchicalStreamReader来遍历文档。这可能与@Dave 建议的 Simple 非常相似。
回答by dinukadev
As others suggested, a Stax model would be a better approach to minimize the memory foot print since it is a push based model. I have personally used Axio (Which is used in Apache Axis) and parse elements using XPath expressions which is less verbose than going through node elements as you have done in the code snippet provided.
正如其他人所建议的那样,Stax 模型将是最小化内存占用的更好方法,因为它是基于推送的模型。我个人使用了 Axio(在 Apache Axis 中使用)并使用 XPath 表达式解析元素,这比您在提供的代码片段中所做的通过节点元素更简洁。
回答by Ian Roberts
In SAX the parser "pushes" events at your handler, so you have to do all the housekeeping as you are used to here. An alternative would be StAX (the javax.xml.stream
package), which is still streaming but your code is responsible for "pulling" events from the parser. This way the logic of what elements are expected in what order is encoded in the control flow of your program rather than having to be explicitly represented in booleans.
在 SAX 中,解析器在您的处理程序处“推送”事件,因此您必须像在这里习惯的那样进行所有的内务处理。另一种选择是 StAX(javax.xml.stream
包),它仍在流式传输,但您的代码负责从解析器“拉”事件。这样,在程序的控制流中编码了哪些元素以什么顺序预期的逻辑,而不必用布尔值显式表示。
Depending on the precise structure of the XML there may be a "middle way" using a toolkit like XOM, which has a mode of operation where you parse a subtree of the document into a DOM-like object model, process that twig, then throw it away and parse the next one. This is good for repetitive documents with many similar elements that can each be processed in isolation - you get the ease of programming to a tree-based API within each twig but still have the streaming behaviour that lets you parse huge documents efficiently.
根据 XML 的精确结构,可能有一种“中间方式”使用像XOM这样的工具包,它具有一种操作模式,您可以将文档的子树解析为类似 DOM 的对象模型,处理该树枝,然后抛出它离开并解析下一个。这对于具有许多相似元素的重复文档很有用,每个元素都可以单独处理 - 您可以轻松地对每个树枝内的基于树的 API 进行编程,但仍然具有流行为,可以让您有效地解析大型文档。
public class ItemProcessor extends NodeFactory {
private Nodes emptyNodes = new Nodes();
public Nodes finishMakingElement(Element elt) {
if("Item".equals(elt.getLocalName())) {
// process the Item element here
System.out.println(elt.getFirstChildElement("ItemId").getValue()
+ ": " + elt.getFirstChildElement("ItemName").getValue());
// then throw it away
return emptyNodes;
} else {
return super.finishMakingElement(elt);
}
}
}
You can achieve a similar thing with a combination of StAX and JAXB - define JAXB annotated classes that represent your repeating element (Item in this example) and then create a StAX parser, navigate to the first Item
start tag, and then you can unmarshal one complete Item
at a time from the XMLStreamReader
.
您可以使用 StAX 和 JAXB 的组合来实现类似的事情 - 定义表示重复元素的 JAXB 注释类(本示例中的 Item),然后创建一个 StAX 解析器,导航到第一个Item
开始标记,然后您可以解组一个完整的Item
一次从XMLStreamReader
.
回答by Twinscode
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
public class JXML {
private DocumentBuilder builder;
private Document doc = null;
private DocumentBuilderFactory factory ;
private XPathExpression expr = null;
private XPathFactory xFactory;
private XPath xpath;
private String xmlFile;
public static ArrayList<String> XMLVALUE ;
public JXML(String xmlFile){
this.xmlFile = xmlFile;
}
private void xmlFileSettings(){
try {
factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
xFactory = XPathFactory.newInstance();
xpath = xFactory.newXPath();
builder = factory.newDocumentBuilder();
doc = builder.parse(xmlFile);
}
catch (Exception e){
System.out.println(e);
}
}
public String[] selectQuery(String query){
xmlFileSettings();
ArrayList<String> records = new ArrayList<String>();
try {
expr = xpath.compile(query);
Object result = expr.evaluate(doc, XPathConstants.NODESET);
NodeList nodes = (NodeList) result;
for (int i=0; i<nodes.getLength();i++){
records.add(nodes.item(i).getNodeValue());
}
return records.toArray(new String[records.size()]);
}
catch (Exception e) {
System.out.println("There is error in query string");
return records.toArray(new String[records.size()]);
}
}
public boolean updateQuery(String query,String value){
xmlFileSettings();
try{
NodeList nodes = (NodeList) xpath.evaluate(query, doc, XPathConstants.NODESET);
for (int idx = 0; idx < nodes.getLength(); idx++) {
nodes.item(idx).setTextContent(value);
}
Transformer xformer = TransformerFactory.newInstance().newTransformer();
xformer.transform(new DOMSource(doc), new StreamResult(new File(this.xmlFile)));
return true;
}catch(Exception e){
System.out.println(e);
return false;
}
}
public static void main(String args[]){
JXML jxml = new JXML("c://user.xml");
jxml.updateQuery("//Order/CustomerId/text()","222");
String result[]=jxml.selectQuery("//Order/Item/*/text()");
for(int i=0;i<result.length;i++){
System.out.println(result[i]);
}
}
}
}