2010-03-02 24 views
17

tôi có một tài liệu năm 1000 nhập có định dạng là một cái gì đó giống nhưĐẩy nhanh xpath

<Example> 
    <Entry> 
      <n1></n1> 
      <n2></n2> 
     </Entry> 
     <Entry> 
      <n1></n1> 
      <n2></n2> 
     </Entry> 
     <!--and so on--> 

Có hơn 1000 nhập nút ở đây. Tôi đang viết một chương trình Java mà về cơ bản nhận được tất cả các nút một và làm một số phân tích trên mỗi nút. Nhưng vấn đề là thời gian truy hồi của các nút tăng lên với số không. Ví dụ, phải mất 78 mili giây để lấy nút đầu tiên 100 ms để lấy nút thứ hai và nó tiếp tục tăng lên. Và để lấy nút 999, phải mất hơn 5 giây. Điều này cực kỳ chậm. Chúng tôi sẽ cắm mã này vào các tệp XML có hơn 1000 mục nhập. Một số như hàng triệu. Tổng thời gian để phân tích toàn bộ tài liệu là hơn 5 phút.

Tôi đang sử dụng mã đơn giản này để duyệt qua nó. Ở đây nxp là lớp của riêng tôi có tất cả các phương thức để lấy các nút từ xpath.

nxp.fromXpathToNode("/Example/Entry" + "[" + i + "]", doc);  

doc là tài liệu cho tệp. i là không có nút nào để truy xuất.

Ngoài ra khi tôi cố gắng một cái gì đó như thế này

List<Node> nl = nxp.fromXpathToNodes("/Example/Entry",doc); 
     content = nl.get(i);  

tôi phải đối mặt với cùng một vấn đề.

Bất cứ ai có bất kỳ giải pháp nào về cách tăng tốc độ tretirival của các nút, vì vậy phải mất một khoảng thời gian tương tự để nhận được nút thứ nhất cũng như nút 1000 từ tệp XML.

Cảm ơn bạn


đây là mã cho 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); 
    } 
} 

và đây là mã dành cho fromxpathtonode.

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; 
} 

và đây là bắt đầu

public class NativeXpathEngine thực hiện XpathEngine
{
tin nhà máy XPathFactory thức;

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>(); 
} 
+0

Mã trong 'fromXpathToNode' và 'fromXpathToNodes 'có vẻ khá liên quan ở đây. Bạn có thể cung cấp mã đó không? –

+0

cần xem mã của bạn tải tài liệu. –

+2

Nếu bạn định truy cập mọi mục nhập, tại sao lại sử dụng XPath? –

Trả lời

1

Bạn đang sử dụng loại trình phân tích cú pháp nào?

DOM kéo toàn bộ tài liệu vào bộ nhớ - khi bạn kéo toàn bộ tài liệu vào bộ nhớ, hoạt động của bạn có thể nhanh nhưng làm như vậy trong ứng dụng web hoặc vòng lặp có thể có tác động.

Trình phân tích cú pháp SAX phân tích cú pháp theo yêu cầu và tải các nút như và khi bạn yêu cầu.

Vì vậy, hãy thử sử dụng triển khai trình phân tích cú pháp phù hợp với nhu cầu của bạn.

+0

Nếu anh ta định sử dụng nó trên một tài liệu với hàng triệu mục, SAX có lẽ là cách tốt hơn để đi. IMHO. –

+0

tôi đang sử dụng trình phân tích cú pháp dom. – jon

+0

nhưng tại sao nó quá chậm. Cần nhanh chóng cho tất cả các thẻ nhập – jon

1

Nếu bạn cần phải phân tích các tài liệu khổng lồ nhưng bằng phẳng, SAX là một lựa chọn tốt. Nó cho phép bạn xử lý XML dưới dạng luồng thay vì xây dựng một DOM khổng lồ.Ví dụ bạn có thể được phân tích bằng cách sử dụng ContentHandler như thế này:

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(); 
     } 
    } 
} 

Nếu tài liệu có cấu trúc sâu hơn và phức tạp hơn, bạn sẽ cần phải sử dụng Ngăn xếp để theo dõi các đường dẫn hiện tại trong tài liệu. Sau đó, bạn nên xem xét việc viết một ContentHandler nhằm mục đích chung để thực hiện công việc dơ bẩn và sử dụng với các trình xử lý phụ thuộc kiểu tài liệu của bạn.

+1

Sử dụng VTD-XML, đó là * giải pháp * :) –

10

Hãy thử VTD-XML. Nó sử dụng ít bộ nhớ hơn DOM. Nó dễ sử dụng hơn SAX và hỗ trợ XPath. Đây là một số mã mẫu để giúp bạn bắt đầu. Nó áp dụng XPath để lấy các phần tử Entry và sau đó in ra các phần tử con n1 và 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++; 
} 
+2

+1 để đề cập đến lib tuyệt vời này. Tôi phải đối mặt với một vấn đề tương tự bằng cách phân tích cú pháp một số xPathExpressions mất gần 1 phút để hoàn thành. VTD-XML thực hiện công việc tương tự trong 2seks. – onigunn

+0

Thư viện được đề cập thực sự tuyệt vời. Tùy thuộc vào trường hợp sử dụng, người ta phải kiểm tra xem việc gửi mã bằng thư viện GPL này có mang phụ thuộc hợp pháp hay không, vì nó được xây dựng dựa trên bằng sáng chế của Hoa Kỳ 7133857, 7260652 và 7761459. – Moreaki

3

Tôi gặp sự cố tương tự với Đánh giá Xpath, tôi đã thử sử dụng CachedXPathAPI nhanh hơn 100X so với XPathApi đã được sử dụng trước đó. thông tin khác về Api này được cung cấp tại đây: http://xml.apache.org/xalan-j/apidocs/org/apache/xpath/CachedXPathAPI.html

Hy vọng điều đó sẽ hữu ích. Chúc mừng, Madhusudhan