у меня есть 1 000 документов записи, формат которых - что-то как
<Example>
<Entry>
<n1></n1>
<n2></n2>
</Entry>
<Entry>
<n1></n1>
<n2></n2>
</Entry>
<!--and so on-->
Здесь существует больше чем 1 000 узлов Записи. Я пишу программу Java, которая в основном получает весь узел один за другим, и сделайте некоторый анализ на каждом узле. Но проблема состоит в том, что время поиска узлов увеличивается с нет. Например, требуется 78 миллисекунд для получения первого узла 100 мс для получения второго, и это продолжает увеличиваться. И получать 999 узлов это берет более, чем 5-секундный. Это чрезвычайно медленно. Мы включили бы этот код к XML-файлам, которые имеют даже больше чем 1 000 записей. Некоторые любят миллионы. Общее время для парсинга целого документа составляет больше чем 5 минут.
Я использую этот простой код для пересечения его. Здесь nxp
мой собственный класс, который имеет все методы для получения узлов от xpath.
nxp.fromXpathToNode("/Example/Entry" + "[" + i + "]", doc);
и doc
документ для файла. i
не узел для получения.
Также, когда я пробую что-то вроде этого
List<Node> nl = nxp.fromXpathToNodes("/Example/Entry",doc);
content = nl.get(i);
Я сталкиваюсь с той же проблемой.
У любого есть любое решение о том, как ускорить tretirival узлов, таким образом, это занимает то же количество времени для получения 1-го узла, а также 1 000 узлов от XML-файла.
Спасибо
вот код для xpathtonode.
public Node fromXpathToNode(String expression, Node context)
{
try
{
return (Node)this.getCachedExpression(expression).evaluate(context, XPathConstants.NODE);
}
catch (Exception cause)
{
throw new RuntimeException(cause);
}
}
и вот код для fromxpathtonodes.
public List<Node> fromXpathToNodes(String expression, Node context)
{
List<Node> nodes = new ArrayList<Node>();
NodeList results = null;
try
{
results = (NodeList)this.getCachedExpression(expression).evaluate(context, XPathConstants.NODESET);
for (int index = 0; index < results.getLength(); index++)
{
nodes.add(results.item(index));
}
}
catch (Exception cause)
{
throw new RuntimeException(cause);
}
return nodes;
}
и вот запуск
общедоступный класс NativeXpathEngine реализует XpathEngine
{
частная заключительная фабрика XPathFactory;
private final XPath engine;
/**
* Cache for previously compiled XPath expressions. {@link XPathExpression#hashCode()}
* is not reliable or consistent so use the textual representation instead.
*/
private final Map<String, XPathExpression> cachedExpressions;
public NativeXpathEngine()
{
super();
this.factory = XPathFactory.newInstance();
this.engine = factory.newXPath();
this.cachedExpressions = new HashMap<String, XPathExpression>();
}
Используйте библиотеку JAXEN для xpaths: http://jaxen.codehaus.org/
Если вам нужно разобрать огромные, но плоские документы, SAX является хорошей альтернативой. Он позволяет обрабатывать XML как поток вместо того, чтобы создавать огромный DOM. Ваш пример можно разобрать с помощью ContentHandler, например, так:
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.ext.DefaultHandler2;
public class ExampleHandler extends DefaultHandler2 {
private StringBuffer chars = new StringBuffer(1000);
private MyEntry currentEntry;
private MyEntryHandler myEntryHandler;
ExampleHandler(MyEntryHandler myEntryHandler) {
this.myEntryHandler = myEntryHandler;
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
chars.append(ch);
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
if ("Entry".equals(localName)) {
myEntryHandler.handle(currentEntry);
currentEntry = null;
}
else if ("n1".equals(localName)) {
currentEntry.setN1(chars.toString());
}
else if ("n2".equals(localName)) {
currentEntry.setN2(chars.toString());
}
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
chars.setLength(0);
if ("Entry".equals(localName)) {
currentEntry = new MyEntry();
}
}
}
Если документ имеет более глубокую и сложную структуру, вам потребуется использовать стеки для отслеживания текущего пути в документе. Тогда вам следует подумать о написании ContentHandler общего назначения для выполнения грязной работы и использования с обработчиками, зависящими от типа документа.
Какой парсер вы используете?
DOM тянет весь документ в память - если вы тянете весь документ в память, то ваши операции могут быть быстрыми, но если вы делаете это в веб-приложении или в цикле for, то это может иметь последствия.
Парсер SAX выполняет парсинг по требованию и загружает узлы по мере поступления запроса.
Поэтому старайтесь использовать ту реализацию парсера, которая соответствует вашим потребностям.
Попробуйте VTD-XML. Он использует меньше памяти, чем DOM. Он проще в использовании, чем SAX, и поддерживает XPath. Вот пример кода, который поможет вам начать работу. Он применяет XPath для получения элементов Entry, а затем выводит дочерние элементы n1 и n2.
final VTDGen vg = new VTDGen();
vg.parseFile("/path/to/file.xml", false);
final VTDNav vn = vg.getNav();
final AutoPilot ap = new AutoPilot(vn);
ap.selectXPath("/Example/Entry");
int count = 1;
while (ap.evalXPath() != -1) {
System.out.println("Inside Entry: " + count);
//move to n1 child
vn.toElement(VTDNav.FIRST_CHILD, "n1");
System.out.println("\tn1: " + vn.toNormalizedString(vn.getText()));
//move to n2 child
vn.toElement(VTDNav.NEXT_SIBLING, "n2");
System.out.println("\tn2: " + vn.toNormalizedString(vn.getText()));
//move back to parent
vn.toElement(VTDNav.PARENT);
count++;
}