2011-06-24 11 views
5

Używam javax.xml.xpath do wyszukiwania określonych ciągów w plikach xml, jednak ze względu na ogromną liczbę plików xml, które muszą być przeszukiwane, jest to znacznie wolniejsze niż oczekiwano.Szybsza api niż javax.xml.xpath do parsowania xml dla wartości?

Czy są jakieś api obsługiwane przez java, które jest szybsze niż javax.xml.xpath lub które jest najszybsze, które jest dostępne?

+1

Być może niewłaściwie używasz interfejsu API. Nowy interfejs API nie jest magicznym pociskiem. Pokaż nam swój kod, być może możemy zaproponować ulepszenia. – skaffman

+0

Mogę wygwizdywać tutaj, ale czy próbowałeś używać wyrażeń regularnych? Regeksy nie będą działać dla wszystkich typów plików xml, ale jeśli struktura jest dość prosta i masz pewność, że wyrazy regularne nie spowodują problemu, może przyspieszyć ten proces. – Augusto

+0

@skaffman, przykro mi nie mogę podzielić się kodem z powodu polityki firmy – Nohsib

Odpowiedz

9

Jak wskazano w artykule skaffman, należy upewnić się, że używasz bibliotek javax.xml.xpath tak skutecznie, jak to możliwe. Jeśli wykonujesz instrukcję XPath bardziej, gdy chcesz ją skompilować do postaci XPathExpression.

XPathExpression xPathExpression = xPath.compile("/root/device/modelname"); 
nl = (NodeList) xPathExpression.evaluate(dDoc, XPathConstants.NODESET); 

Demo

W opcji Przykład # 2 będzie szybsze niż opcji # 1.

import java.io.File; 

import javax.xml.parsers.DocumentBuilder; 
import javax.xml.parsers.DocumentBuilderFactory; 
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 Demo { 

    public static void main(String[] args) { 
     DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); 
     try { 
      DocumentBuilder builder = domFactory.newDocumentBuilder(); 
      File xml = new File("input.xml"); 
      Document dDoc = builder.parse(xml); 

      NodeList nl; 

      // OPTION #1 
      XPath xPath = XPathFactory.newInstance().newXPath(); 
      nl = (NodeList) xPath.evaluate("root/device/modelname", dDoc, XPathConstants.NODESET); 
      printResults(nl); 
      nl = (NodeList) xPath.evaluate("/root/device/modelname", dDoc, XPathConstants.NODESET); 
      printResults(nl); 

      // OPTION #2 
      XPathExpression xPathExpression = xPath.compile("/root/device/modelname"); 
      nl = (NodeList) xPathExpression.evaluate(dDoc, XPathConstants.NODESET); 
      printResults(nl); 
      nl = (NodeList) xPathExpression.evaluate(dDoc, XPathConstants.NODESET); 
      printResults(nl); 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    private static void printResults(NodeList nl) { 
     for(int x=0; x<nl.getLength(); x++) { 
      System.out.println("the value is: " + nl.item(x).getTextContent()); 
     } 
    } 

} 

input.xml

<?xml version="1.0" encoding="UTF-8"?> 
<root> 
    <blah>foo</blah> 
    <device> 
    <modelname>xbox</modelname> 
    </device> 
    <blah>bar</blah> 
    <device> 
    <modelname>wii</modelname> 
    </device> 
    <blah/> 
</root> 
1

możesz obejrzeć mój poprzedni answer za coś pokrewnego.

Zasadniczo użyłem JXpath i Xerces, a także Dom4J i javax. Mogę powiedzieć z przekonaniem z mojego doświadczenia, że ​​VTD-XML jest najszybszy z tych opcji.

Istnieje wiele innych pytań dotyczących używania VTD-XML na SO, jeśli zależy Ci na wyszukiwaniu.

EDIT:
ok, więc na podstawie Twojego komentarza fragment kodu będzie coś takiego:

VTDGen vg = new VTDGen(); 
AutoPilot ap = new AutoPilot(); 
int i; 
ap.selectXPath("/root/device/modelname"); 
if (vg.parseFile(PATH_TO_FILE,true)){ 
    VTDNav vn = vg.getNav(); 
    ap.bind(vn); // apply XPath to the VTDNav instance 
    // AutoPilot moves the cursor for you 
    while((i=ap.evalXPath())!=-1){ 
     System.out.println("the value is: " + vn.toNormalizedString(vn.getText())); 
    } 
} 

Na poniższym XML:

<root> 
    <blah>foo</blah> 
    <device> 
    <modelname>xbox</modelname> 
    </device> 
    <blah>bar</blah> 
    <device> 
    <modelname>wii</modelname> 
    </device> 
    <blah/> 
</root> 

wyjście będzie:

the value is: xbox 
the value is: wii 

Możesz go zabrać stąd ...

+1

Zajmę się twoim rozwiązaniem, dziękuję. – Nohsib

+1

@ Asaf: jeśli mam ciąg s = " ... ..... xbox .... ..." jak użyć VTD-XML, aby uzyskać wartość w węźle modelname, można uprzejmie udostępniasz fragment kodu. – Nohsib

+1

@Nohsib, edytował odpowiedź z fragmentem kodu. powinno być wystarczająco jasne – Asaf

4

Zastanawiam się, czy wyszukiwanie XPath jest naprawdę Twój gardłem, czy to faktycznie parsowanie XML? Podejrzewam to drugie. Nie wiem, jak trwałe są twoje dokumenty XML, ale myślę, że rozwiązaniem będzie przechowywanie ich w bazie danych XML, abyś tylko raz ponosił koszty analizy, aby można je było zaindeksować, aby XPath/XQuery były bardziej wydajne .

0

Powinieneś opracować, jakiego rodzaju rzeczy szukasz - jeśli są to zwykłe ciągi treści, rozważałbym na przykład użycie Stax API (javax.xml.stream.XMLStreamReader). XPath jest dobry, jeśli chcesz ograniczyć wyszukiwanie określonego podzbioru.

Jednym z problemów z XPath jest jednak to, że w zależności od wyrażenia może to skutkować budowaniem drzewa DOM w pamięci, a to jest dość kosztowne (w odniesieniu do przetwarzania XML), zarówno pod względem prędkości, jak i użycia pamięci. Więc jeśli można tego uniknąć, to samo może przyspieszyć przetwarzanie przez fabrykę 3x.

Powiązane problemy