2010-03-26 35 views
5

NHIỆM VỤ: Tôi có tài liệu xml hiện có (UTF-8) sử dụng không gian tên xml và lược đồ xml. Tôi cần phải phân tích cú pháp thành một phần tử cụ thể, nối thêm nội dung (cũng cần phải sử dụng tiền tố không gian tên xml) cho phần tử này và sau đó viết lại Tài liệu.Trình phân tích cú pháp Xml java tốt nhất để thao tác/chỉnh sửa tài liệu xml hiện có

thư viện phân tích cú pháp XML nào tốt nhất mà tôi nên sử dụng cho TASK này?

Tôi đã xem một chuỗi trước (Best XML parser for Java) nhưng không chắc liệu dom4j hay JDOM có tốt cho không gian tên/xmlSchema và hỗ trợ tốt cho các ký tự UTF-8 hay không.

Một số phân tích cú pháp đó có vẻ như một nhiệm vụ cho
JDOM
Dom4J
XOM
Woodstock

Bất kỳ ý tưởng nào là tốt nhất? :-) Tôi sử dụng JDK 6 và không muốn sử dụng các tiện ích SAX/DOM tích hợp để thực hiện công việc này vì điều đó đòi hỏi tôi phải viết quá nhiều mã.

Sẽ giúp bạn có một số ví dụ về thực hiện tác vụ như vậy.

+0

như thế nào làm điều đó với built-in DOM cơ sở sẽ là quá nhiều mã? Ah, phải - Java ... ;-) Nhưng nghiêm túc: 15-20 dòng có quá nhiều mã theo ý kiến ​​của bạn không? Điều gì sẽ là chấp nhận được? – Thomas

+0

Các lib xử lý xml tốt nhất cho nhiệm vụ nặng nề là vtd-xml, thanh không ... http://sdiwc.us/digitlib/journal_paper.php?paper=00000582.pdf –

Trả lời

5

Sử dụng JDOM, lấy một InputStream và làm cho nó một tài liệu:

InputStream inputStream = (InputStream)httpURLConnection.getContent(); 
DocumentBuilderFactory docbf = DocumentBuilderFactory.newInstance(); 
docbf.setNamespaceAware(true); 
DocumentBuilder docbuilder = docbf.newDocumentBuilder(); 
Document document = docbuilder.parse(inputStream, baseUrl); 

Vào thời điểm đó, bạn có XML trong một đối tượng Java. Làm xong. Dễ dàng.

Bạn có thể sử dụng đối tượng tài liệu và API Java để chỉ đọc qua nó hoặc cũng sử dụng XPath mà tôi thấy dễ dàng hơn (khi tôi đã học được).

Xây dựng một đối tượng XPath, mà phải mất một chút:

public static XPath buildXPath() { 
    XPathFactory factory = XPathFactory.newInstance(); 
    XPath xpath = factory.newXPath(); 
    xpath.setNamespaceContext(new AtomNamespaceContext()); 
    return xpath; 
} 


public class AtomNamespaceContext implements NamespaceContext { 

    public String getNamespaceURI(String prefix) { 
     if (prefix == null) 
      throw new NullPointerException("Null prefix"); 
     else if ("a".equals(prefix)) 
      return "http://www.w3.org/2005/Atom"; 
     else if ("app".equals(prefix)) 
      return "http://www.w3.org/2007/app"; 
     else if ("os".equals(prefix)) 
      return "http://a9.com/-/spec/opensearch/1.1/"; 
     else if ("x".equals(prefix)) 
      return "http://www.w3.org/1999/xhtml"; 
     else if ("xml".equals(prefix)) 
      return XMLConstants.XML_NS_URI; 
     return XMLConstants.NULL_NS_URI; 
    } 

    // This method isn't necessary for XPath processing. 
    public String getPrefix(String uri) { 
     throw new UnsupportedOperationException(); 
    } 

    // This method isn't necessary for XPath processing either. 
    public Iterator getPrefixes(String uri) { 
     throw new UnsupportedOperationException(); 
    } 
} 

Sau đó, chỉ cần sử dụng nó, mà (may mắn) không mất nhiều thời gian ở tất cả:

return Integer.parseInt(xpath.evaluate("/a:feed/os:totalResults/text()", document)); 
+0

+1 - JDOM là API dễ học nhất cho điều này. XSLT sẽ là một lựa chọn tốt hơn nếu bạn có các tác vụ như thế này thường xuyên. – jsight

5

Sử dụng XSLT. Nghiêm túc. Đây là một công việc hoàn hảo cho nó. Chỉ cần sử dụng một mẫu sao chép để sao chép mọi thứ ngoại trừ nơi bạn cần thêm xml. Bạn thậm chí có thể thêm XML bằng cách viết XML thực sự thay vì thao tác DOM.

Đây là bản sao mẫu:

<xsl:template match="node() | @*"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
</xsl:template> 

Tôi biết rất nhiều người ghét XSLT, nhưng đây là một nhiệm vụ mà nó sẽ thực sự tỏa sáng và mất hầu như không có mã. Ngoài ra, bạn chỉ có thể sử dụng những gì trong JDK.

1

Có vẻ như bạn có thể viết một tờ kiểu xslt để thực hiện những gì bạn muốn.

2

Kể từ khi viết quá nhiều mã là vấn đề chính đối với bạn, bạn có thể muốn xem xét jOOX:

http://code.google.com/p/joox/

Tôi đã tạo ra jOOX là một cổng của jQuery tới Java. Công nghệ cơ bản là DOM chuẩn của Java.Một số mẫu mã:

// Find the order at index for and add an element "paid" 
$(document).find("orders").children().eq(4) 
      .append("<paid>true</paid>"); 

// Find those orders that are paid and flag them as "settled" 
$(document).find("orders").children().find("paid") 
      .after("<settled>true</settled>"); 

// Add a complex element 
$(document).find("orders").append(
    $("order", $("date", "2011-08-14"), 
      $("amount", "155"), 
      $("paid", "false"), 
      $("settled", "false")).attr("id", "13"); 

Lưu ý: Không gian tên chưa được hỗ trợ một cách rõ ràng, nhưng bạn có thể làm việc xung quanh rằng

+0

jOOX là ý tưởng hay. Nhưng tôi đã mất thời gian, bởi vì công nghệ này không hỗ trợ thao tác với các thuộc tính. Không có nó, công nghệ này chỉ thích hợp cho việc đọc. – wojand

+0

@wojand: Điều gì khiến bạn nghĩ vậy? jOOX cho phép thao tác các thuộc tính. Xem ví dụ thứ ba trong câu trả lời của tôi, trong đó đặt 'id =" 13 "' –

+0

Chỉ cho tôi cách thêm thuộc tính vào thẻ hiện tại. Bạn có thể thêm thẻ, nhưng vấn đề là khi bạn cần thêm thuộc tính vào thẻ hiện tại. Tôi không thể tìm thấy một giải pháp đơn giản. Tôi không tìm thấy bất kỳ ví dụ nào trên trang jOOX cho vấn đề này. Phía trên thẻ nối ví dụ của bạn với thuộc tính, nhưng cách CHỈ PHẢI CHỈ MỘT thuộc tính cho $ {} KHÔNG CÓ thẻ? – wojand

Các vấn đề liên quan