如何提高使用 VTD-XML 和 XPath 查询 xml 文件的性能?
How to improve performance of querying xml file with VTD-XML and XPath?
我正在查询 XML 个大小约为 1 MB(超过 20k 行)的文件。我正在使用 XPath 来描述我想要获取的内容,并使用 VTD-XML 库来获取它。我认为我的性能有问题。
问题是,我正在对 XML 文件进行大约 5k+ 次查询。检索所有值大约需要 16-17 秒。我想问你,这是否是执行此类任务的正常表现?我该如何改进它?
我正在使用 VTD-XML 库和 AutoPilot 导航方法,这让我有机会使用 XPath。实现如下:
private VTDGen vg = new VTDGen();
private VTDNav vn;
private AutoPilot ap = new AutoPilot();
public void init(String xml) {
log.info("Creating document");
xml = xml.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
byte[] bytes = xml.getBytes(StandardCharsets.UTF_8);
vg.setDoc(bytes);
try {
vg.parse(true);
vn = vg.getNav();
} catch (ParseException e) {
e.printStackTrace();
}
log.info("Document created");
}
public String parseXmlOrReturnNull(String query) {
String xPathStringVal = null;
try {
ap.selectXPath(query);
ap.bind(vn);
int i = -1;
while ((i = ap.evalXPath()) != -1) {
xPathStringVal = vn.getXPathStringVal();
}
}catch (XPathEvalException e) {
e.printStackTrace();
} catch (NavException e) {
e.printStackTrace();
} catch (XPathParseException e) {
e.printStackTrace();
}
return xPathStringVal;
}
我的 xml 文件有特定的格式,它们分为很多部分 - 段,我的查询对所有段都是相同的(我在循环中查询)。例如 xml 的一部分:
<segment>
<a>
<b>value1</b>
<c>
<d>value2</d>
<e>value3</d>
</c>
</a>
</segment>
<segment>
<a>
<b>value4</b>
<c>
<d>value5</d>
<e>value6</d>
<f>value6</d>
</c>
</a>
</segment>
...
如果我想在第一段中获取值 1,我正在使用查询:
//segment[1]/a/b
第二段中的值 4
//segment[2]/a/b
等等
直觉说明了一些事情:在我的方法中,每个查询都是独立的(它对其他查询一无所知),这意味着我的迭代器 AutoPilot 总是在我想要的时候从文件的开头开始查询它。
我的问题是:有什么方法可以在处理段开始时设置AutoPilot吗?当我完成查询时,将 AutoPilot 移动到下一个航段?我认为,如果我的方法不是从头开始搜索值,而是从指定点开始搜索值,它会快得多。
另一种方法是将xml个文件分成小的xml个文件(一个xml个文件=一个段),然后查询那些xml个小文件。
大家怎么看?提前致谢
次要:UTF-8为默认编码,无需替换;只有当 是 一种编码时,才需要将其修补为 UTF-8。
XPath 应该只执行一次,而不是从 [0] 开始到下一个索引。
如果您需要列表表示,您可以使用带有注释的 JAXB。
基于事件的原语解析没有 DOM 对象可能是最好的(SAXParser)。
Handler handler = new org.xml.sax.helpers.DefaultHandler {
@Override
public void startElement(String uri,
String localName, String qName, Attributes attributes) throws SAXException {
}
@Override
public void endElement(String uri,
String localName, String qName) throws SAXException {
}
@Override
public void characters(char ch[], int start, int length) throws SAXException {
}
};
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
InputStream in = new ByteArrayInputStream(bytes);
parser.parse(in, handler);
我正在查询 XML 个大小约为 1 MB(超过 20k 行)的文件。我正在使用 XPath 来描述我想要获取的内容,并使用 VTD-XML 库来获取它。我认为我的性能有问题。
问题是,我正在对 XML 文件进行大约 5k+ 次查询。检索所有值大约需要 16-17 秒。我想问你,这是否是执行此类任务的正常表现?我该如何改进它?
我正在使用 VTD-XML 库和 AutoPilot 导航方法,这让我有机会使用 XPath。实现如下:
private VTDGen vg = new VTDGen();
private VTDNav vn;
private AutoPilot ap = new AutoPilot();
public void init(String xml) {
log.info("Creating document");
xml = xml.replace("<?xml version=\"1.0\"?>", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
byte[] bytes = xml.getBytes(StandardCharsets.UTF_8);
vg.setDoc(bytes);
try {
vg.parse(true);
vn = vg.getNav();
} catch (ParseException e) {
e.printStackTrace();
}
log.info("Document created");
}
public String parseXmlOrReturnNull(String query) {
String xPathStringVal = null;
try {
ap.selectXPath(query);
ap.bind(vn);
int i = -1;
while ((i = ap.evalXPath()) != -1) {
xPathStringVal = vn.getXPathStringVal();
}
}catch (XPathEvalException e) {
e.printStackTrace();
} catch (NavException e) {
e.printStackTrace();
} catch (XPathParseException e) {
e.printStackTrace();
}
return xPathStringVal;
}
我的 xml 文件有特定的格式,它们分为很多部分 - 段,我的查询对所有段都是相同的(我在循环中查询)。例如 xml 的一部分:
<segment>
<a>
<b>value1</b>
<c>
<d>value2</d>
<e>value3</d>
</c>
</a>
</segment>
<segment>
<a>
<b>value4</b>
<c>
<d>value5</d>
<e>value6</d>
<f>value6</d>
</c>
</a>
</segment>
...
如果我想在第一段中获取值 1,我正在使用查询:
//segment[1]/a/b
第二段中的值 4
//segment[2]/a/b
等等
直觉说明了一些事情:在我的方法中,每个查询都是独立的(它对其他查询一无所知),这意味着我的迭代器 AutoPilot 总是在我想要的时候从文件的开头开始查询它。
我的问题是:有什么方法可以在处理段开始时设置AutoPilot吗?当我完成查询时,将 AutoPilot 移动到下一个航段?我认为,如果我的方法不是从头开始搜索值,而是从指定点开始搜索值,它会快得多。
另一种方法是将xml个文件分成小的xml个文件(一个xml个文件=一个段),然后查询那些xml个小文件。
大家怎么看?提前致谢
次要:UTF-8为默认编码,无需替换;只有当 是 一种编码时,才需要将其修补为 UTF-8。
XPath 应该只执行一次,而不是从 [0] 开始到下一个索引。
如果您需要列表表示,您可以使用带有注释的 JAXB。
基于事件的原语解析没有 DOM 对象可能是最好的(SAXParser)。
Handler handler = new org.xml.sax.helpers.DefaultHandler {
@Override
public void startElement(String uri,
String localName, String qName, Attributes attributes) throws SAXException {
}
@Override
public void endElement(String uri,
String localName, String qName) throws SAXException {
}
@Override
public void characters(char ch[], int start, int length) throws SAXException {
}
};
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
InputStream in = new ByteArrayInputStream(bytes);
parser.parse(in, handler);