|
|
| 53行目: |
53行目: |
| if (xml.hasError()) { | | if (xml.hasError()) { |
| std::cerr << QString("XML Error : %1").arg(xml.errorString()).toStdString() << std::endl; | | std::cerr << QString("XML Error : %1").arg(xml.errorString()).toStdString() << std::endl; |
| }
| |
| </syntaxhighlight>
| |
| <br><br>
| |
|
| |
| == Xerces-C++ライブラリ ==
| |
| ==== Xerces-C++ライブラリとは ====
| |
| Apache XMLプロジェクトにより開発されたXMLパーサライブラリである。<br>
| |
| C++で実装されており、XMLドキュメントの解析、生成、変更が可能であり、W3C標準に準拠しており、高度な機能を持つ。<br>
| |
| <br>
| |
| Xerces-C++ライブラリは、以下に示す特徴を持つ。<br>
| |
| * W3C標準準拠
| |
| *: XML 1.0 / 1.1、DOM Level 1 / 2 / 3、SAX 1 / 2、XInclude、XML Schema、XPath、XSLT、名前空間等のXMLに関連する多くのW3C標準に準拠している。
| |
| * 高機能
| |
| *: 豊富な機能セットを持っており、XMLドキュメントの解析、検証、変更、生成等が可能である。
| |
| *: また、XPathやXSLT等の高度な機能もサポートしている。
| |
| * 安定性と信頼性
| |
| *: Apache XMLプロジェクトにより長年開発され続けており、安定性と信頼性が高い。
| |
| *: エンタープライズアプリケーションでの使用実績がある。
| |
| * 拡張性
| |
| *: プラグイン機構により、独自の機能を簡単に拡張できる。
| |
| *: 例えば、独自のXMLスキーマや文字エンコーディングを追加することが可能である。
| |
| * マルチスレッド対応
| |
| *: マルチスレッドプログラミングをサポートしている。
| |
| <br>
| |
| ただし、Xerces-C++ライブラリは大規模なライブラリであるため、導入や習得にコストがかかる可能性がある。<br>
| |
| また、パフォーマンス面では軽量なライブラリよりも劣ることがある。<br>
| |
| <br>
| |
| そのため、プロジェクトの要件次第では、TinyXMLやRapidXml等の軽量ライブラリも選択肢として検討する必要がある。<br>
| |
| <br>
| |
| 一般的には、Xerces-C++ライブラリは高機能で標準準拠のXMLパーサーライブラリであり、本格的なXMLハンドリングが必要な場合に使用する。<br>
| |
| <br>
| |
| ==== インストール ====
| |
| ===== パッケージ管理システムからインストール =====
| |
| # RHEL
| |
| sudo dnf install xerces-c-devel
| |
|
| |
| # SUSE
| |
| sudo zypper install libxerces-c-devel
| |
| <br>
| |
|
| |
| ===== ソースコードからインストール =====
| |
| Xerces-C++ライブラリのビルドに必要なライブラリをインストールする。<br>
| |
| # RHEL
| |
| sudo dnf install make cmake gcc gcc-c++ libcurl-devel libicu-devel
| |
|
| |
| # SUSE
| |
| sudo zypper install make cmake gcc gcc-c++ libcurl-devel libicu-devel
| |
| <br>
| |
| [https://xerces.apache.org/xerces-c/download.cgi Xerces-C++ライブラリの公式Webサイト]にアクセスして、ソースコードをダウンロードする。<br>
| |
| ダウンロードしたファイルを解凍する。<br>
| |
| tar xf xerces-c-<バージョン>.tar.xz
| |
| cd xerces-c-<バージョン>
| |
| <br>
| |
| Xerces-C++ライブラリをビルドおよびインストールする。<br>
| |
| mkdir build && cd build
| |
|
| |
| cmake .. \
| |
| -DCMAKE_INSTALL_PREFIX=<Xerces-C++ライブラリのインストールディレクトリ> \
| |
| -DCMAKE_BUILD_TYPE=Release \
| |
| -Dmessage-loader=icu \ # オプション : 内部UTF-16と他のエンコーディングとの変換に使用するトランスコーダを指定する
| |
| # 他に、inmemoryまたはiconv等も指定することができる
| |
| -Dmessage-loader=icu # オプション : 診断メッセージへのアクセスに使用するメッセージローダを指定する
| |
| # 他に、gnuiconvまたはiconvを指定することもできる
| |
| -Dnetwork-accessor=curl # オプション : ネットワークリソースへのアクセスに使用するライブラリを指定する
| |
| # 他に、"socket"を指定することもできる
| |
|
| |
| make -j $(nproc)
| |
| make install
| |
| <br>
| |
| ==== サンプルコード ====
| |
| サンプルコードでは、以下に示すような手順を行っている。<br>
| |
| # まず、<code>XMLPlatformUtils::Initialize</code>メソッドを実行して、Xerces-C++ライブラリを初期化する。
| |
| # 次に、<code>XercesDOMParser</code>クラスのインスタンスを生成して、XMLドキュメントを解析する。
| |
| # <code>getDocument</code>メソッドを実行してDOMドキュメントを取得して、<code>getDocumentElement</code>メソッドを実行してルート要素を取得する。
| |
| # ルート要素の名前を出力する。
| |
| # <code>getChildNodes</code>メソッドを実行してルート要素の子要素のリストを取得する。(各子要素の名前を出力)
| |
| # <code>XMLPlatformUtils::Terminate</code>メソッドを実行して、Xerces-C++ライブラリを解放する。
| |
| <br>
| |
| 以下の例で使用しているXMLファイルの内容を示す。
| |
| <syntaxhighlight lang="xml">
| |
| <?xml version="1.0" encoding="UTF-8"?>
| |
| <root>
| |
| <child1>
| |
| <grandchild>Value1</grandchild>
| |
| </child1>
| |
| <child2 attr="value">
| |
| <grandchild>Value2</grandchild>
| |
| </child2>
| |
| <child3/>
| |
| </root>
| |
| </syntaxhighlight>
| |
| <br>
| |
| <syntaxhighlight lang="c++">
| |
| #include <iostream>
| |
| #include <string>
| |
| #include <xercesc/util/PlatformUtils.hpp>
| |
| #include <xercesc/dom/DOM.hpp>
| |
| #include <xercesc/parsers/XercesDOMParser.hpp>
| |
|
| |
| using namespace xercesc;
| |
|
| |
| int main(int argc, char* argv[])
| |
| {
| |
| try {
| |
| // Xerces-C++ライブラリの初期化
| |
| XMLPlatformUtils::Initialize();
| |
|
| |
| // XMLドキュメントを解析するパーサーを作成
| |
| XercesDOMParser parser;
| |
| parser.setValidationScheme(XercesDOMParser::Val_Always); // オプションでXMLスキーマ検証を行う
| |
|
| |
| // XMLファイルを指定してパースする
| |
| parser.parse("example.xml");
| |
|
| |
| // ルート要素を取得
| |
| DOMDocument* document = parser.getDocument();
| |
| DOMElement* rootElement = document->getDocumentElement();
| |
|
| |
| // ルート要素の名前を出力
| |
| char* rootName = XMLString::transcode(rootElement->getTagName());
| |
| std::cout << "Root element name: " << rootName << std::endl;
| |
| XMLString::release(&rootName);
| |
|
| |
| // 子要素を取得して出力
| |
| DOMNodeList* childNodes = rootElement->getChildNodes();
| |
| for (XMLSize_t i = 0; i < childNodes->getLength(); i++) {
| |
| DOMNode* childNode = childNodes->item(i);
| |
| if (childNode->getNodeType() == DOMNode::ELEMENT_NODE) {
| |
| DOMElement* childElement = static_cast<DOMElement*>(childNode);
| |
| char* childName = XMLString::transcode(childElement->getTagName());
| |
| std::cout << "Child element name: " << childName << std::endl;
| |
| XMLString::release(&childName);
| |
| }
| |
| }
| |
|
| |
| // Xerces-C++ライブラリの終了処理
| |
| XMLPlatformUtils::Terminate();
| |
| }
| |
| catch (const XMLException& e) {
| |
| char* message = XMLString::transcode(e.getMessage());
| |
| std::cout << "Error: " << message << std::endl;
| |
| XMLString::release(&message);
| |
| }
| |
| catch (const DOMException& e) {
| |
| char* message = XMLString::transcode(e.msg);
| |
| std::cout << "Error: " << message << std::endl;
| |
| XMLString::release(&message);
| |
| }
| |
| catch (...) {
| |
| std::cout << "Unexpected error occurred" << std::endl;
| |
| }
| |
|
| |
| return 0;
| |
| } | | } |
| </syntaxhighlight> | | </syntaxhighlight> |
概要
QXmlStreamReaderクラス
QXmlStreamReaderクラスとは
QXmlStreamReaderクラスは、XMLをシンプルなストリーミングAPIで読み込むための高速パーサである。
ストリームリーダの基本的なコンセプトは、XMLドキュメントをトークンのストリームとして読み込むことである。
QXmlStreamReaderクラスとSAXの主な違いは、これらのXMLトークンの読み込み手順である。
- SAXの場合
- アプリケーションはパーサの都合に合わせてパーサからXMLイベントを受信するハンドラ (コールバック関数) を提供する必要がある。
- QXmlStreamReaderの場合
- 繰り返し文を使用して、必要なトークンを次々にリーダから取り出すことができる。
- これは、
readNextメソッドを呼び出すことで実行され、リーダは次のトークンを完了するまで入力ストリームから読み取り、tokenTypeメソッドを返す。
- その後、
isStartElementメソッドやtextメソッド等を使用してトークンを確認することにより、読み込まれているタグや要素についての情報を得ることができる。
このプルアプローチのメリットは、再帰降順パーサを構築して、XMLを異なるメソッドやクラスに分割できることである。
これにより、XMLの解析を簡単に追跡することができる。
要素の取得例
以下の例では、XMLファイルを読み込み、要素titleの値を抽出してコンソールへ出力している。
#include <QXmlStreamReader>
#include <QFile>
#include <QTextStream>
// XMLファイルを開く
QFile File("<XMLファイルのパス 例: hoge.xml>");
if(!File.open(QIODevice::ReadOnly)) {
std::cout << QString("ファイルのオープンに失敗 : %1").arg(File.errorString()) << std::endl;
return;
}
// XMLファイルを読み込む
QTextStream InStream(&File);
QString XMLData = InStream.readAll();
File.close();
// XMLファイルから特定の要素を抽出
QXmlStreamReader xml(XMLData);
while (!xml.atEnd() && !xml.hasError()) {
QXmlStreamReader::TokenType token = xml.readNext();
if (token == QXmlStreamReader::StartElement) {
if (xml.name() == "title") {
// 特定の要素が存在する場合は値をコンソールへ出力
xml.readNext();
std::cout << QString("Title : %1").arg(xml.text().toString()).toStdString() << std::endl;
}
}
}
if (xml.hasError()) {
std::cerr << QString("XML Error : %1").arg(xml.errorString()).toStdString() << std::endl;
}