Tôi nên sử dụng trình phân tích cú pháp XML nào trong C ++? [đóng cửa]


344

Tôi có các tài liệu XML mà tôi cần phân tích cú pháp và / hoặc tôi cần xây dựng các tài liệu XML và viết chúng vào văn bản (cả tệp hoặc bộ nhớ). Vì thư viện chuẩn C ++ không có thư viện cho việc này, tôi nên sử dụng cái gì?

Lưu ý: Đây được dự định là một câu hỏi dứt khoát, C ++ - Câu hỏi thường gặp cho câu hỏi này. Vì vậy, có, nó là một bản sao của người khác. Tôi không chỉ đơn giản là thích hợp với những câu hỏi khác bởi vì họ có xu hướng yêu cầu một cái gì đó cụ thể hơn một chút. Câu hỏi này là chung chung hơn.


Tôi như tiCpp code.google.com/p/ticpp , các tài liệu này là không lớn (chưa?), Nhưng tôi yêu thư viện, mã sạch đẹp.

Câu trả lời:


679

Cũng giống như với các thùng chứa thư viện tiêu chuẩn, thư viện nào bạn nên sử dụng phụ thuộc vào nhu cầu của bạn. Đây là một sơ đồ thuận tiện:

nhập mô tả hình ảnh ở đây

Vì vậy, câu hỏi đầu tiên là: bạn cần gì?

Tôi cần tuân thủ Full XML

OK, vì vậy bạn cần xử lý XML. Không phải đồ chơi XML, XML thật . Bạn cần có khả năng đọc và viết tất cả các đặc tả XML, không chỉ các bit thấp, dễ phân tích cú pháp. Bạn cần không gian tên, DocTypes, thay thế thực thể, các tác phẩm. Toàn bộ Đặc tả XML của W3C.

Câu hỏi tiếp theo là: API của bạn có cần tuân thủ DOM hoặc SAX không?

Tôi cần Chính xác DOM và / hoặc SAX Phù hợp

OK, vì vậy bạn thực sự cần API là DOM và / hoặc SAX. Nó không chỉ là trình phân tích cú pháp đẩy kiểu SAX hoặc trình phân tích cú pháp giữ lại kiểu DOM. Nó phải là DOM thực tế hoặc SAX thực tế, trong phạm vi mà C ++ cho phép.

Bạn đã lựa chọn:

Xerces

Đó là sự lựa chọn của bạn. Đó là khá nhiều trình phân tích / trình phân tích cú pháp XML C ++ duy nhất có đầy đủ (hoặc gần như C ++ cho phép) tuân thủ DOM và SAX. Nó cũng có hỗ trợ XInclude, hỗ trợ Lược đồ XML và rất nhiều tính năng khác.

Nó không có phụ thuộc thực sự. Nó sử dụng giấy phép Apache.

Tôi không quan tâm đến sự phù hợp của DOM và / hoặc SAX

Bạn đã lựa chọn:

LibXML2

LibXML2 cung cấp giao diện kiểu C (nếu điều đó thực sự làm phiền bạn, hãy sử dụng Xerces), mặc dù giao diện ít nhất là dựa trên đối tượng và dễ dàng bao bọc. Nó cung cấp rất nhiều tính năng, như hỗ trợ XInclude (với các cuộc gọi lại để bạn có thể biết nó lấy tệp từ đâu), trình nhận dạng XPath 1.0, hỗ trợ thư giãn và Schematron (mặc dù các thông báo lỗi rất mong muốn) và v.v.

Nó có một sự phụ thuộc vào iconv, nhưng nó có thể được cấu hình mà không cần sự phụ thuộc đó. Mặc dù điều đó có nghĩa là bạn sẽ có một bộ mã hóa văn bản có thể hạn chế hơn, nó có thể phân tích cú pháp.

Nó sử dụng giấy phép MIT.

Tôi không cần tuân thủ XML đầy đủ

OK, vì vậy việc tuân thủ XML đầy đủ không thành vấn đề với bạn. Các tài liệu XML của bạn hoàn toàn nằm dưới sự kiểm soát của bạn hoặc được đảm bảo sử dụng "tập hợp con cơ bản" của XML: không có không gian tên, thực thể, v.v.

Vậy điều gì quan trọng với bạn? Câu hỏi tiếp theo là: Điều quan trọng nhất đối với bạn trong công việc XML của bạn là gì?

Hiệu suất phân tích cú pháp XML tối đa

Ứng dụng của bạn cần lấy XML và biến nó thành cơ sở dữ liệu C ++ nhanh nhất có thể xảy ra chuyển đổi này.

Bạn đã lựa chọn:

RapidXML

Trình phân tích cú pháp XML này chính xác như những gì nó nói trên tin: XML nhanh. Nó thậm chí không đối phó với việc kéo tập tin vào bộ nhớ; Làm thế nào điều đó xảy ra là tùy thuộc vào bạn. Những gì nó giải quyết là phân tích nó thành một chuỗi các cấu trúc dữ liệu C ++ mà bạn có thể truy cập. Và nó thực hiện việc này nhanh như việc quét từng tệp byte theo byte.

Tất nhiên, không có gì gọi là bữa trưa miễn phí. Giống như hầu hết các trình phân tích cú pháp XML không quan tâm đến đặc tả XML, Rapid XML không chạm vào các không gian tên, DocTypes, các thực thể (ngoại trừ các thực thể ký tự và 6 thực thể XML cơ bản), v.v. Vì vậy, về cơ bản các nút, các yếu tố, thuộc tính, và như vậy.

Ngoài ra, nó là một trình phân tích cú pháp kiểu DOM. Vì vậy, nó yêu cầu bạn phải đọc tất cả các văn bản. Tuy nhiên, những gì nó không làm là sao chép bất kỳ văn bản nào (thông thường). Cách RapidXML đạt được hầu hết tốc độ của nó là bằng cách tham chiếu đến các chuỗi tại chỗ . Điều này đòi hỏi quản lý bộ nhớ nhiều hơn về phía bạn (bạn phải giữ cho chuỗi đó tồn tại trong khi RapidXML đang xem xét nó).

DOM của RapidXML là xương sống. Bạn có thể nhận được các giá trị chuỗi cho mọi thứ. Bạn có thể tìm kiếm các thuộc tính theo tên. Đó là về nó. Không có chức năng tiện lợi để biến các thuộc tính thành các giá trị khác (số, ngày, v.v.). Bạn chỉ cần có được chuỗi.

Một nhược điểm khác với RapidXML là việc viết XML rất khó khăn. Nó đòi hỏi bạn phải thực hiện nhiều phân bổ bộ nhớ rõ ràng cho các tên chuỗi để xây dựng DOM của nó. Nó cung cấp một loại bộ đệm chuỗi, nhưng điều đó vẫn đòi hỏi nhiều công việc rõ ràng về phía bạn. Nó chắc chắn có chức năng, nhưng nó là một nỗi đau để sử dụng.

Nó sử dụng giấy phép MIT. Nó là một thư viện chỉ có tiêu đề không có phụ thuộc.

Tôi quan tâm đến hiệu suất nhưng không quá nhiều

Vâng, hiệu suất quan trọng với bạn. Nhưng có lẽ bạn cần một cái gì đó ít xương trần. Có thể một cái gì đó có thể xử lý nhiều Unicode hơn hoặc không yêu cầu quản lý bộ nhớ do người dùng kiểm soát nhiều. Hiệu suất vẫn quan trọng, nhưng bạn muốn một cái gì đó ít trực tiếp hơn.

Bạn đã lựa chọn:

PugiXML

Trong lịch sử, điều này phục vụ như là nguồn cảm hứng cho RapidXML. Nhưng hai dự án đã chuyển hướng, với Pugi cung cấp nhiều tính năng hơn, trong khi RapidXML tập trung hoàn toàn vào tốc độ.

PugiXML cung cấp hỗ trợ chuyển đổi Unicode, vì vậy nếu bạn có một số tài liệu UTF-16 xung quanh và muốn đọc chúng dưới dạng UTF-8, Pugi sẽ cung cấp. Nó thậm chí còn có triển khai XPath 1.0, nếu bạn cần loại đó.

Nhưng Pugi vẫn khá nhanh. Giống như RapidXML, nó không có phụ thuộc và được phân phối theo Giấy phép MIT.

Đọc tài liệu khổng lồ

Bạn cần đọc các tài liệu được đo bằng kích thước gigabyte . Có lẽ bạn đang nhận được chúng từ stdin, được nuôi dưỡng bởi một số quy trình khác. Hoặc bạn đang đọc chúng từ các tập tin lớn. Hay bất cứ cái gì. Vấn đề là, điều bạn cần là không phải đọc toàn bộ tập tin vào bộ nhớ cùng một lúc để xử lý nó.

Bạn đã lựa chọn:

LibXML2

API kiểu SAX của Xerces sẽ hoạt động trong khả năng này, nhưng LibXML2 có ở đây vì nó dễ làm việc hơn một chút. API kiểu SAX là API đẩy: nó bắt đầu phân tích cú pháp một luồng và chỉ thực hiện các sự kiện mà bạn phải nắm bắt. Bạn bị buộc phải quản lý bối cảnh, nhà nước, v.v. Mã đọc API kiểu SAX trải rộng hơn nhiều so với người ta có thể hy vọng.

xmlReaderĐối tượng của LibXML2 là một API kéo. Bạn yêu cầu đi đến nút hoặc phần tử XML tiếp theo; bạn không nói Điều này cho phép bạn lưu trữ ngữ cảnh khi bạn thấy phù hợp, để xử lý các thực thể khác nhau theo cách mã dễ đọc hơn nhiều so với một loạt các cuộc gọi lại.

Lựa chọn thay thế

Người nước ngoài

Expat là một trình phân tích cú pháp C ++ nổi tiếng sử dụng API trình phân tích cú pháp kéo. Nó được viết bởi James Clark.

Tình trạng hiện tại của nó đang hoạt động. Phiên bản gần đây nhất là 2.2.9, được phát hành vào ngày (2019-09-25).

LlamaXML

Đây là một triển khai API kiểu StAX. Nó là một trình phân tích cú pháp kéo, tương tự như xmlReadertrình phân tích cú pháp của LibXML2 .

Nhưng nó đã không được cập nhật từ năm 2005. Vì vậy, một lần nữa, Caveat Emptor.

Hỗ trợ XPath

XPath là một hệ thống để truy vấn các phần tử trong cây XML. Đây là một cách tiện dụng để đặt tên hiệu quả cho một thành phần hoặc tập hợp phần tử theo các thuộc tính chung, sử dụng cú pháp được tiêu chuẩn hóa. Nhiều thư viện XML cung cấp hỗ trợ XPath.

Có ba lựa chọn hiệu quả ở đây:

  • LibXML2 : Nó cung cấp hỗ trợ XPath 1.0 đầy đủ. Một lần nữa, nó là API C, vì vậy nếu làm phiền bạn, có những lựa chọn thay thế.
  • PugiXML : Nó cũng hỗ trợ XPath 1.0. Như trên, đó là API C ++ nhiều hơn LibXML2, vì vậy bạn có thể thoải mái hơn với nó.
  • TinyXML : Nó không hỗ trợ XPath, nhưng có thư viện TinyXPath cung cấp nó. TinyXML đang trải qua quá trình chuyển đổi sang phiên bản 2.0, điều này làm thay đổi đáng kể API, vì vậy TinyXPath có thể không hoạt động với API mới. Giống như TinyXML, TinyXPath được phân phối theo giấy phép zLib.

Chỉ cần hoàn thành công việc

Vì vậy, bạn không quan tâm đến tính chính xác của XML. Hiệu suất không phải là một vấn đề cho bạn. Truyền phát là không liên quan. Tất cả những gì bạn muốn là thứ gì đó đưa XML vào bộ nhớ và cho phép bạn dán lại vào đĩa. Điều bạn quan tâm là API.

Bạn muốn một trình phân tích cú pháp XML sẽ nhỏ, dễ cài đặt, tầm thường để sử dụng và đủ nhỏ để không liên quan đến kích thước thực thi cuối cùng của bạn.

Bạn đã lựa chọn:

TinyXML

Tôi đặt TinyXML vào vị trí này bởi vì nó đơn giản để sử dụng như trình phân tích cú pháp XML. Vâng, nó chậm, nhưng nó đơn giản và rõ ràng. Nó có rất nhiều chức năng tiện lợi để chuyển đổi các thuộc tính và vv.

Viết XML không có vấn đề gì trong TinyXML. Bạn chỉ cần newlên một số đối tượng, gắn chúng lại với nhau, gửi tài liệu cho a std::ostreamvà mọi người đều vui vẻ.

Ngoài ra còn có một cái gì đó của một hệ sinh thái được xây dựng xung quanh TinyXML, với API thân thiện hơn với trình lặp và thậm chí là triển khai XPath 1.0 nằm trên nó.

TinyXML sử dụng giấy phép zLib, ít nhiều là Giấy phép MIT với một tên khác.


6
Điều này trông hơi giống như một bản sao dán. Bạn có thể liên kết các tài liệu nguồn?
Joel

28
@Joel: khá thường xuyên khi ai đó trả lời câu hỏi của chính họ bằng một bài đăng dài, đó là vì họ đang làm theo tinh thần lời khuyên của Jeff - đặc biệt là vì những gì trông giống như một câu hỏi thường có thể được đóng lại trước khi một câu trả lời hay có thể được đăng, nếu người đó đang viết câu trả lời ngay lúc đó và ở đó. Bằng cách dành chút thời gian để chuẩn bị câu trả lời trước khi anh ấy đặt câu hỏi :) Nicol sẽ cung cấp cho tất cả chúng ta một ứng cử viên xuất sắc cho Đóng-> Câu hỏi trùng lặp trong tương lai.
sarnold

28
@Joel: Tôi sợ tôi không thể. Nó chỉ là một tài liệu tạm thời tôi đã sao chép từ trong Notepad ++. Tôi chưa bao giờ lưu nó, vì vậy tôi không thể liên kết bạn với nó;)
Nicol Bolas

6
Có thể đáng nói đến phiên bản mới hơn của TinyXML: TinyXML-2 sử dụng API tương tự như TinyXML-1 và các trường hợp thử nghiệm phong phú tương tự. Nhưng việc thực hiện trình phân tích cú pháp được viết lại hoàn toàn để làm cho nó phù hợp hơn để sử dụng trong một trò chơi. Nó sử dụng ít bộ nhớ hơn, nhanh hơn và sử dụng rất ít phân bổ bộ nhớ.
johnbakers

6
Tôi thích câu hỏi và câu trả lời này, nhưng thấy nó quá thiên về Unix. Không đề cập đến MSXML và XmlLite? Nếu tính di động đa paltform là lý do của bạn để loại trừ những cái đó, thì điều này nên được đề cập rõ ràng trong câu hỏi và câu trả lời. (Nếu một số người có thể kết thúc việc lựa chọn ví dụ như libxml2 cho một dự án Windows mà thôi, đó là yêu cầu cho đau đầu mà có thể dễ dàng tránh được.)
Scrontch

17

Có một cách tiếp cận khác để xử lý XML mà bạn có thể muốn xem xét, được gọi là ràng buộc dữ liệu XML. Đặc biệt là nếu bạn đã có một đặc tả chính thức về từ vựng XML của mình, ví dụ, trong Lược đồ XML.

Liên kết dữ liệu XML cho phép bạn sử dụng XML mà không cần thực hiện bất kỳ phân tích cú pháp hoặc tuần tự hóa XML nào. Trình biên dịch liên kết dữ liệu tự động tạo ra tất cả các mã cấp thấp và trình bày dữ liệu được phân tích cú pháp dưới dạng các lớp C ++ tương ứng với miền ứng dụng của bạn. Sau đó, bạn làm việc với dữ liệu này bằng cách gọi các hàm và làm việc với các loại C ++ (int, double, v.v.) thay vì so sánh các chuỗi và phân tích văn bản (đó là những gì bạn làm với các API truy cập XML cấp thấp như DOM hoặc SAX).

Xem, ví dụ, một triển khai liên kết dữ liệu XML nguồn mở mà tôi đã viết, CodeSynt tổng hợp XSD và, đối với phiên bản nhẹ hơn, không phụ thuộc, CodeSynt tổng hợp XSD / e .


13
Tôi không quan tâm đến bài đăng, nhưng chính sách SO nói rằng nếu bạn đề xuất một cái gì đó bạn đã viết, bạn nên đề cập rằng bạn đã viết nó, vì lợi ích của việc tiết lộ đầy đủ.
Nicol Bolas

@Nicol Tôi đã chỉnh sửa nó thành câu trả lời.
JBentley

Có lẽ hữu ích là danh sách này nhưng tôi không thể tìm ra ai là tác giả của danh sách đó (mà không tiết lộ công khai tôi không thể xem các mô tả và xếp hạng có ý nghĩa hay không). Có lẽ người ta có thể nhìn vào nhóm làm việc liên kết dữ liệu W3C liệt kê một số công cụ liên kết dữ liệu trong miền công cộng và được sử dụng để thử nghiệm và báo cáo (tiết lộ đầy đủ: Tôi không liên kết với CodeSynt tổng hợp, tôi đã giúp gsoap được liệt kê với W3C công cụ).
Tiến sĩ Alex RE

1

Một lưu ý khác về Expat: đáng để các hệ thống nhúng hoạt động. Tuy nhiên, tài liệu bạn có thể tìm thấy trên web là cổ xưa và sai. Mã nguồn thực sự có các nhận xét cấp độ chức năng khá kỹ lưỡng, nhưng sẽ cần một số hiểu biết để chúng có ý nghĩa.



0

Được rồi Tôi đã tạo một cái mới, vì không ai trong danh sách không đáp ứng nhu cầu của tôi.

Những lợi ích:

  1. API phân tích cú pháp kéo xuống ở mức thấp ( Java StAX như )
  2. Ngoại lệ và chế độ RTTI được hỗ trợ
  3. Giới hạn cho việc sử dụng bộ nhớ, hỗ trợ cho các tệp lớn (được thử nghiệm với tệp XMark 100 mib từ, tốc độ phụ thuộc vào phần cứng)
  4. Hỗ trợ UNICODE và tự động phát hiện mã hóa nguồn đầu vào
  5. API cấp cao để đọc vào cấu trúc / POCO
  6. API lập trình meta để viết và tạo XSD từ cấu trúc / POCO có hỗ trợ cấu trúc xml (thuộc tính và thẻ lồng nhau) (thế hệ XSD cần RTTI, nhưng chỉ có thể được sử dụng khi gỡ lỗi để tạo một lần)
  7. C ++ 11 - GCC và VC ++ 15+

Nhược điểm:

  1. Xác nhận DTD và XSD chưa được cung cấp
  2. Đang xử lý XML / XSD bằng HTTP / HTTPS, chưa được thực hiện
  3. Thư viện mới

Nhà dự án


1
Bạn có thể thêm điểm chuẩn?
Vadim Peretokin

-1

Trong Secured Globe , Inc. chúng tôi sử dụng quickxml . Chúng tôi đã thử tất cả những thứ khác nhưng quickxml dường như là lựa chọn tốt nhất cho chúng tôi.

Đây là một ví dụ:

 rapidxml::xml_document<char> doc;
    doc.parse<0>(xmlData);
    rapidxml::xml_node<char>* root = doc.first_node();

    rapidxml::xml_node<char>* node_account = 0;
    if (GetNodeByElementName(root, "Account", &node_account) == true)
    {
        rapidxml::xml_node<char>* node_default = 0;
        if (GetNodeByElementName(node_account, "default", &node_default) == true)
        {
            swprintf(result, 100, L"%hs", node_default->value());
            free(xmlData);
            return true;
        }
    }
    free(xmlData);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.