📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

文字列「__FORCETOC__」を「{{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This pag…
 
(同じ利用者による、間の10版が非表示)
404行目: 404行目:
<br><br>
<br><br>


== libxml2ライブラリ ==
==== libxml2ライブラリとは ====
libxml2ライブラリは、XMLの解析と操作を行うための広く使用されているオープンソースライブラリである。<br>
C言語で記述されており、多くのプログラミング言語から利用できる。<br>
効率的なメモリ管理と高速な処理を実現しており、様々なOSで動作する。<br>
<br>
libxml2ライブラリは、XMLドキュメントの読み込み、解析、作成、変更、検証といった基本的な機能を提供している。<br>
<br>
XMLの構文解析においては、DOMとSAXの両方のアプローチをサポートしている。<br>
DOMは文書全体をメモリ上に木構造として読み込むため、文書全体を操作する必要がある場合に適している。<br>
一方、SAXはイベントベースの解析を行い、大規模な文書を効率的に処理する場合に有用である。<br>
<br>
また、libxml2ライブラリは、XMLスキーマやDTDを用いた文書の検証、XPath式を使用したXML文書内の特定の要素や属性の検索、XSLT変換の実行等、<br>
XMLに関連する多くの標準技術もサポートしている。
<br>
セキュリティ面では、libxml2ライブラリは入力の検証やエンティティの展開制限などの機能を備えており、XML外部実体攻撃 (XXE) 等の脆弱性に対する保護を提供する。<br>
<br>
上記の特徴により、libxml2ライブラリはWebサービス、CMS、データ交換アプリケーション等、XMLを扱う多くのソフトウェアプロジェクトで採用されている。<br>
<br>
==== libxml2ライブラリのライセンス ====
libxml2ライブラリのライセンスは、MITライセンスに準拠している。<br>
<br>
==== libxml2ライブラリのインストール ====
===== パッケージ管理システムからインストール =====
# RHEL
sudo dnf install libxml2-devel
# SUSE
sudo zypper install libxml2-devel
<br>
===== ソースコードからインストール =====
libxml2ライブラリのビルドに必要なライブラリをインストールする。<br>
# RHEL
sudo dnf install cmake python3-devel \
                  zlib-devel        # zlibライブラリを使用する場合
                  xz-devel          # lzmaライブラリを使用する場合
                  readline-devel    # Readlineライブラリを使用する場合
                  libicu-devel      # ICUライブラリを使用する場合
                  meson ninja-build  # MesonおよびNinjaでビルドする場合
# SUSE
sudo zypper install cmake python3-devel \
                    zlib-devel      # zlibライブラリを使用する場合
                    xz-devel        # lzmaライブラリを使用する場合
                    readline-devel  # Readlineライブラリを使用する場合
                    libicu-devel    # ICUライブラリを使用する場合
                    meson ninja    # MesonおよびNinjaでビルドする場合
<br>
[https://gitlab.gnome.org/GNOME/libxml2 libxml2ライブラリのGithub]、または、[https://github.com/GNOME/libxml2 libxml2ライブラリのGithub]にアクセスして、ソースコードをダウンロードする。<br>
ダウンロードしたファイルを解凍する。<br>
tar xf libxml2-v<バージョン>.tar.gz
cd libxml2-v<バージョン>
<br>
libxml2ライブラリをビルドおよびインストールする。<br>
mkdir build && cd build
# CMakeを使用する場合
cmake -DCMAKE_BUILD_TYPE=Release  \
      -DCMAKE_INSTALL_PREFIX=<libxml2ライブラリのインストールディレクトリ> \
      -DLIBXML2_WITH_HTTP=ON      \  # HTTPをサポートする場合
      -DLIBXML2_WITH_READLINE=ON  \  # Readlineを使用する場合
      -DLIBXML2_WITH_ICU=ON      \  # ICUライブラリを使用する場合
      -DLIBXML2_WITH_ZLIB=ON      \  # zlibライブラリを使用する場合
      -DLIBXML2_WITH_LZMA=ON      \  # lzmaライブラリを使用する場合
      ..
make -j $(nproc)
make install
# MesonおよびNinjaを使用する場合
meson setup ./build                                  \
    -Dprefix=<libxml2ライブラリのインストールディレクトリ> \
    -Dhttp=enabled                                  \
    -Dicu=enabled                                    \
    -Dlzma=enabled                                  \
    -Dzlib=enabled
ninja -C ./build
ninja -C ./build install
<br>
==== Qtプロジェクトファイル (.pro) を使用する場合 ====
<syntaxhighlight lang="make">
# Qtプロジェクトファイル (.pro)
# Pkg-configを使用する場合
CONFIG += link_pkgconfig
PKGCONFIG += libxml-2.0
# Pkg-Configを使用しない場合
INCLUDEPATH += /usr/include/libxml2
LIBS += -lxml2
</syntaxhighlight>
<br>
==== CMakeを使用する場合 ====
<syntaxhighlight lang="cmake">
# CMakeLists.txtファイル
 
# pkg-configを使うための準備
find_package(PkgConfig REQUIRED)
# pkg-configを使用してlibxml2ライブラリを検索
pkg_search_module(LIBXML2 REQUIRED libxml-2.0)
# ライブラリのインクルードディレクトリをターゲットに追加
include_directories(${LIBXML2_INCLUDE_DIRS})
# ライブラリのリンクディレクトリをターゲットに追加
link_directories(${LIBXML2_LIBRARY_DIRS})
target_include_directories(<プロジェクト名> PRIVATE
    # ...略
    ${LIBXML2_INCLUDE_DIRS}
)
target_link_libraries(<プロジェクト名>
    # ...略
    ${LIBXML2_LIBRARIES}
)
# libxml2のコンパイルオプション
add_definitions(
    # ...略
    ${LIBXML2_CFLAGS_OTHER}
)
</syntaxhighlight>
<br>
==== 要素の取得 ====
以下の例では、指定されたXML構造を持つXMLファイルを読み込み取得している。<br>
<br>
読み込むXMLファイルを以下に示す。<br>
<syntaxhighlight lang="xml">
<!-- 使用するXMLファイル -->
<Earthquake>
  <OriginTime>2024-08-23T21:00:00+09:00</OriginTime>
  <ArrivalTime>2024-08-23T21:01:00+09:00</ArrivalTime>
  <Hypocenter>
    <Area>
      <Name>茨城県南部</Name>
      <Code type="震央地名">301</Code>
    </Area>
  </Hypocenter>
  <jmx_eb:Magnitude type="Mj" description="M3.8">3.8</jmx_eb:Magnitude>
</Earthquake>
<Observation>
  <Pref><Name>茨城県</Name><Code>08</Code><MaxInt>2</MaxInt>
    <Area><Name>茨城県北部</Name><Code>300</Code><MaxInt>2</MaxInt>
      <City><Name>小美玉市</Name><Code>0823600</Code><MaxInt>2</MaxInt>
        <IntensityStation><Name>小美玉市小川*</Name><Code>0823633</Code><Int>2</Int></IntensityStation>
        <IntensityStation><Name>小美玉市上玉里*</Name><Code>0823635</Code><Int>2</Int></IntensityStation>
      </City>
      <City><Name>水戸市</Name><Code>0820100</Code><MaxInt>1</MaxInt>
        <IntensityStation><Name>水戸市千波町*</Name><Code>0820121</Code><Int>1</Int></IntensityStation>
      </City>
    </Area>
  </Pref>
</Observation>
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// XMLParser.hファイル
#ifndef XMLPARSER_H
#define XMLPARSER_H
#include <QString>
#include <QVector>
#include <libxml/parser.h>
#include <libxml/tree.h>
class XMLParser {
private:
    static QString getNodeContent(xmlNodePtr node);
public:
    static QString getHypocenterAreaName(const QString& xmlContent);
    static QString getHypocenterAreaCodeType(const QString& xmlContent);
    static QVector<QString> getIntensityStationNames(const QString& xmlContent);
};
QString XMLParser::getNodeContent(xmlNodePtr node)
{
    if (node && node->children && node->children->content) {
      return QString::fromUtf8(reinterpret_cast<const char*>(node->children->content));
    }
    return QString();
}
QString XMLParser::getHypocenterAreaName(const QString& xmlContent)
{
    xmlDocPtr doc = xmlReadMemory(xmlContent.toUtf8().constData(), xmlContent.toUtf8().size(), NULL, NULL, 0);
    if (!doc) return QString();
    xmlNodePtr root = xmlDocGetRootElement(doc);
    xmlNodePtr current = root;
    while (current) {
      if (QString::fromUtf8(reinterpret_cast<const char*>(current->name)) == "Hypocenter") {
          xmlNodePtr area = current->children;
          while (area) {
            if (QString::fromUtf8(reinterpret_cast<const char*>(area->name)) == "Area") {
                xmlNodePtr name = area->children;
                while (name) {
                  if (QString::fromUtf8(reinterpret_cast<const char*>(name->name)) == "Name") {
                      QString result = getNodeContent(name);
                      xmlFreeDoc(doc);
                      return result;
                  }
                  name = name->next;
                }
            }
            area = area->next;
          }
      }
      current = current->next;
    }
    xmlFreeDoc(doc);
    return QString();
}
QString XMLParser::getHypocenterAreaCodeType(const QString& xmlContent)
{
    xmlDocPtr doc = xmlReadMemory(xmlContent.toUtf8().constData(), xmlContent.toUtf8().size(), NULL, NULL, 0);
    if (!doc) return QString();
    xmlNodePtr root = xmlDocGetRootElement(doc);
    xmlNodePtr current = root;
    while (current) {
      if (QString::fromUtf8(reinterpret_cast<const char*>(current->name)) == "Hypocenter") {
          xmlNodePtr area = current->children;
          while (area) {
            if (QString::fromUtf8(reinterpret_cast<const char*>(area->name)) == "Area") {
                xmlNodePtr code = area->children;
                while (code) {
                  if (QString::fromUtf8(reinterpret_cast<const char*>(code->name)) == "Code") {
                      xmlChar *type = xmlGetProp(code, reinterpret_cast<const xmlChar*>("type"));
                      if (type) {
                        QString result = QString::fromUtf8(reinterpret_cast<const char*>(type));
                        xmlFree(type);
                        xmlFreeDoc(doc);
                        return result;
                      }
                  }
                  code = code->next;
                }
            }
            area = area->next;
          }
      }
      current = current->next;
    }
    xmlFreeDoc(doc);
    return QString();
}
QVector<QString> XMLParser::getIntensityStationNames(const QString& xmlContent)
{
    QVector<QString> results;
    xmlDocPtr doc = xmlReadMemory(xmlContent.toUtf8().constData(), xmlContent.toUtf8().size(), NULL, NULL, 0);
    if (!doc) return results;
    xmlNodePtr root = xmlDocGetRootElement(doc);
    xmlNodePtr current = root;
    while (current) {
      if (QString::fromUtf8(reinterpret_cast<const char*>(current->name)) == "Observation") {
          xmlNodePtr pref = current->children;
          while (pref) {
            if (QString::fromUtf8(reinterpret_cast<const char*>(pref->name)) == "Pref") {
                xmlNodePtr area = pref->children;
                while (area) {
                  if (QString::fromUtf8(reinterpret_cast<const char*>(area->name)) == "Area") {
                      xmlNodePtr city = area->children;
                      while (city) {
                        if (QString::fromUtf8(reinterpret_cast<const char*>(city->name)) == "City") {
                            xmlNodePtr station = city->children;
                            while (station) {
                              if (QString::fromUtf8(reinterpret_cast<const char*>(station->name)) == "IntensityStation") {
                                  xmlNodePtr name = station->children;
                                  while (name) {
                                    if (QString::fromUtf8(reinterpret_cast<const char*>(name->name)) == "Name") {
                                        results.append(getNodeContent(name));
                                    }
                                    name = name->next;
                                  }
                              }
                              station = station->next;
                            }
                        }
                        city = city->next;
                      }
                  }
                  area = area->next;
                }
            }
            pref = pref->next;
          }
      }
      current = current->next;
    }
    xmlFreeDoc(doc);
    return results;
}
#endif // XMLPARSER_H
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
#include <QCoreApplication>
#include <QFile>
#include "xmlparser.h"
#include <QDebug>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QFile file("earthquake.xml");
    if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
      qDebug() << "Failed to open file";
      return -1;
    }
    QString xmlContent = file.readAll();
    file.close();
    QString hypocenterAreaName = XMLParser::getHypocenterAreaName(xmlContent);
    QString hypocenterAreaCodeType = XMLParser::getHypocenterAreaCodeType(xmlContent);
    QVector<QString> intensityStationNames = XMLParser::getIntensityStationNames(xmlContent);
    qDebug() << "Hypocenter Area Name:" << hypocenterAreaName;
    qDebug() << "Hypocenter Area Code Type:" << hypocenterAreaCodeType;
    qDebug() << "Intensity Station Names:";
    for (const auto& name : intensityStationNames) {
      qDebug() << "  -" << name;
    }
    return a.exec();
}
</syntaxhighlight>
<br>
==== XMLファイルの作成 ====
以下の例では、指定されたXML構造を持つXMLファイルを作成している。<br>
<br>
<syntaxhighlight lang="xml">
<!-- 作成するXMLファイルの構造 -->
<Earthquake>
  <OriginTime>2024-08-23T21:00:00+09:00</OriginTime>
  <ArrivalTime>2024-08-23T21:01:00+09:00</ArrivalTime>
  <Hypocenter>
    <Area>
      <Name>茨城県南部</Name>
      <Code type="震央地名">301</Code>
    </Area>
  </Hypocenter>
  <jmx_eb:Magnitude type="Mj" description="M3.8">3.8</jmx_eb:Magnitude>
</Earthquake>
<Observation>
  <Pref><Name>茨城県</Name><Code>08</Code><MaxInt>2</MaxInt>
    <Area><Name>茨城県北部</Name><Code>300</Code><MaxInt>2</MaxInt>
      <City><Name>小美玉市</Name><Code>0823600</Code><MaxInt>2</MaxInt>
        <IntensityStation><Name>小美玉市小川*</Name><Code>0823633</Code><Int>2</Int></IntensityStation>
        <IntensityStation><Name>小美玉市上玉里*</Name><Code>0823635</Code><Int>2</Int></IntensityStation>
      </City>
      <City><Name>水戸市</Name><Code>0820100</Code><MaxInt>1</MaxInt>
        <IntensityStation><Name>水戸市千波町*</Name><Code>0820121</Code><Int>1</Int></IntensityStation>
      </City>
    </Area>
  </Pref>
</Observation>
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
// XMLCreator.hファイル
#ifndef XMLCREATOR_H
#define XMLCREATOR_H
#include <QString>
#include <QVector>
#include <libxml/tree.h>
class XMLCreator {
public:
    static void createXML(const QString& filename,
                          const QString& hypocenterAreaName,
                          const QString& hypocenterAreaCodeType,
                          const QVector<QString>& intensityStationNames);
private:
    static xmlNodePtr createHypocenter(xmlDocPtr doc, const QString& areaName, const QString& codeType);
    static xmlNodePtr createObservation(xmlDocPtr doc, const QVector<QString>& stationNames);
};
void XMLCreator::createXML(const QString& filename,
                            const QString& hypocenterAreaName,
                            const QString& hypocenterAreaCodeType,
                            const QVector<QString>& intensityStationNames)
{
    xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0");
    xmlNodePtr root = xmlNewNode(NULL, BAD_CAST "Report");
    xmlDocSetRootElement(doc, root);
    xmlNodePtr earthquake = xmlNewChild(root, NULL, BAD_CAST "Earthquake", NULL);
    xmlNewChild(earthquake, NULL, BAD_CAST "OriginTime", BAD_CAST "2024-08-23T21:00:00+09:00");
    xmlNewChild(earthquake, NULL, BAD_CAST "ArrivalTime", BAD_CAST "2024-08-23T21:01:00+09:00");
    xmlAddChild(earthquake, createHypocenter(doc, hypocenterAreaName, hypocenterAreaCodeType));
    xmlNodePtr magnitude = xmlNewChild(earthquake, NULL, BAD_CAST "jmx_eb:Magnitude", BAD_CAST "3.8");
    xmlNewProp(magnitude, BAD_CAST "type", BAD_CAST "Mj");
    xmlNewProp(magnitude, BAD_CAST "description", BAD_CAST "M3.8");
    xmlAddChild(root, createObservation(doc, intensityStationNames));
    xmlSaveFormatFileEnc(filename.toUtf8().constData(), doc, "UTF-8", 1);
    xmlFreeDoc(doc);
    xmlCleanupParser();
}
xmlNodePtr XMLCreator::createHypocenter(xmlDocPtr doc, const QString& areaName, const QString& codeType)
{
    xmlNodePtr hypocenter = xmlNewNode(NULL, BAD_CAST "Hypocenter");
    xmlNodePtr area = xmlNewChild(hypocenter, NULL, BAD_CAST "Area", NULL);
    xmlNewChild(area, NULL, BAD_CAST "Name", BAD_CAST areaName.toUtf8().constData());
    xmlNodePtr code = xmlNewChild(area, NULL, BAD_CAST "Code", BAD_CAST "301");
    xmlNewProp(code, BAD_CAST "type", BAD_CAST codeType.toUtf8().constData());
    return hypocenter;
}
xmlNodePtr XMLCreator::createObservation(xmlDocPtr doc, const QVector<QString>& stationNames)
{
    xmlNodePtr observation = xmlNewNode(NULL, BAD_CAST "Observation");
    xmlNodePtr pref = xmlNewChild(observation, NULL, BAD_CAST "Pref", NULL);
    xmlNewChild(pref, NULL, BAD_CAST "Name", BAD_CAST "茨城県");
    xmlNewChild(pref, NULL, BAD_CAST "Code", BAD_CAST "08");
    xmlNewChild(pref, NULL, BAD_CAST "MaxInt", BAD_CAST "2");
    xmlNodePtr area = xmlNewChild(pref, NULL, BAD_CAST "Area", NULL);
    xmlNewChild(area, NULL, BAD_CAST "Name", BAD_CAST "茨城県北部");
    xmlNewChild(area, NULL, BAD_CAST "Code", BAD_CAST "300");
    xmlNewChild(area, NULL, BAD_CAST "MaxInt", BAD_CAST "2");
    xmlNodePtr city = xmlNewChild(area, NULL, BAD_CAST "City", NULL);
    xmlNewChild(city, NULL, BAD_CAST "Name", BAD_CAST "小美玉市");
    xmlNewChild(city, NULL, BAD_CAST "Code", BAD_CAST "0823600");
    xmlNewChild(city, NULL, BAD_CAST "MaxInt", BAD_CAST "2");
    for (const auto& name : stationNames) {
      xmlNodePtr station = xmlNewChild(city, NULL, BAD_CAST "IntensityStation", NULL);
      xmlNewChild(station, NULL, BAD_CAST "Name", BAD_CAST name.toUtf8().constData());
      xmlNewChild(station, NULL, BAD_CAST "Code", BAD_CAST "0823633");
      xmlNewChild(station, NULL, BAD_CAST "Int", BAD_CAST "2");
    }
    return observation;
}
#endif // XMLCREATOR_H
</syntaxhighlight>
<br>
<syntaxhighlight lang="c++">
#include <QCoreApplication>
#include <QFile>
#include "XMLCreator.h"
#include <QDebug>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    QString hypocenterAreaName = "茨城県南部";
    QString hypocenterAreaCodeType = "震央地名";
    QVector<QString> intensityStationNames = {"小美玉市小川*", "小美玉市上玉里*", "水戸市千波町*"};
    QString filename = "earthquake_output.xml";
    XMLCreator::createXML(filename, hypocenterAreaName, hypocenterAreaCodeType, intensityStationNames);
    // ファイルの内容を読み込んで表示
    QFile file(filename);
    if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
      QTextStream in(&file);
      QString content = in.readAll();
      qDebug() << "Created XML content:";
      qDebug().noquote() << content;
      file.close();
    }
    else {
      qDebug() << "Failed to open the created XML file.";
    }
    return a.exec();
}
</syntaxhighlight>
<br><br>
{{#seo:
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux
|image=/resources/assets/MochiuLogo_Single_Blue.png
}}


__FORCETOC__
__FORCETOC__
[[カテゴリ:Qt]]
[[カテゴリ:Qt]]