IXMLSerializable インターフェイスを使用して、XML ファイルからクラスを作成する
アブストラクト
PLCnext Common Classes には、XML シリアライゼーションのサポートが組み込まれていることをご存知ですか?この記事では、IXmlSerializable
の使用方法を示します c++ クラスにデータを取り込むためのインターフェース。
インターフェイスの説明は、PLCnext Common Classes の API ドキュメントに記載されています。
要件
この記事は次の設定で書かれています:
PLCnext ファームウェア:2020.6 LTS PLCnext C++ SDK for Linux 64 ビット 2020.6 LTS
データ
クラスに次の構成ファイルを設定します。
<?xml version="1.0" encoding="UTF-8"?> <MyConfigDocument schemaVersion="1.0"> <Server dnsName="server.domain.tld" /> <FileList> <File path="$ARP_DATA_DIR$/Services/MyComponent/file1.txt" /> <File path="$ARP_DATA_DIR$/Services/MyComponent/file2.txt" /> </FileList> </MyConfigDocument>
$ARP_DATA_DIR$
表記は環境変数のプレースホルダーです。この場合は ARP_DATA_DIR
です。 .定義済みの Arp 環境変数は、ターゲット /etc/plcnext/Device.acf.settings
のデバイス設定ファイルにあります。 .
XML ファイルからデータを読み取れるようにするには、IXMLSerializable
を実装する必要があります。 私たちのクラスのインターフェース。シンプルにするために、このクラスには、DNS 名とファイルパスのベクトルの 2 つのデータ要素しかありません。
#pragma once #include "Arp/System/Core/Arp.h" #include "Arp/System/Commons/Xml/IXmlSerializable.hpp" #include "vector" namespace MyComponent { class MyConfiguration : public Arp::System::Commons::Xml::IXmlSerializable { public: MyConfiguration() = default; ~MyConfiguration() = default; // IXMLSerializable interface public: void ReadXml(Arp::System::Commons::Xml::XmlReader& reader, Arp::System::Commons::Xml::XmlSerializationContext& context) override; void WriteXml(Arp::System::Commons::Xml::XmlWriter& writer, Arp::System::Commons::Xml::XmlSerializationContext& context) override; // The data public: Arp::String DnsName{""}; std::vector<Arp::String> FileList; // Some supporting methods private: void readFileList(Arp::System::Commons::Xml::XmlReader& reader, Arp::System::Commons::Xml::XmlSerializationContext& context); void readFile(Arp::System::Commons::Xml::XmlReader& reader, Arp::System::Commons::Xml::XmlSerializationContext& context); }; } // namespace MyComponent
実装
ReadXml
を実装する必要があります と WriteXml
メソッド。
WriteXml
メソッドは簡単です。XML ファイルからデータを読み取るだけで、書き込みは必要ありません。 ReadXml
XML ファイルからデータを読み取る場合、メソッドが呼び出されます。
#include "MyConfiguration.hpp"
namespace MyComponent
{
void MyConfiguration::WriteXml(Arp::System::Commons::Xml::XmlWriter& writer, Arp::System::Commons::Xml::XmlSerializationContext& context)
{
// no operation.
return;
}
void MyConfiguration::ReadXml(Arp::System::Commons::Xml::XmlReader& reader, Arp::System::Commons::Xml::XmlSerializationContext& context)
{
Arp::String elementName;
while (reader.TryReadStartElement(elementName))
{
if (elementName == Arp::System::Commons::Xml::XmlSerializationContext::IncludesXmlName)
{
context.ReadIncludesElement(reader);
}
else if (elementName == "Server")
{
this->DnsName = reader.GetAttributeValue<Arp::String>("dnsName");
reader.ReadEndElement();
}
else if (elementName == "FileList")
{
this->readFileList(reader, context);
}
else
{
context.InvalidXmlElementOccurs(reader, elementName);
reader.ReadEndElement();
}
}
}
void MyConfiguration::readFileList(Arp::System::Commons::Xml::XmlReader& reader, Arp::System::Commons::Xml::XmlSerializationContext& context)
{
if (reader.IsEmptyElement()){
return;
}
if (reader.ReadToDescendant("File"))
{
this->readFile(reader, context);
while (reader.ReadToNextSibling("File"))
{
this->readFile(reader, context);
}
}
else
{
reader.ReadEndElement();
}
}
void MyConfiguration::readFile(Arp::System::Commons::Xml::XmlReader& reader, Arp::System::Commons::Xml::XmlSerializationContext& context)
{
// Use 'context.ResolvePath' to replace placeholders in the path.
auto file = Arp::String(context.ResolvePath(reader.GetAttributeValue<Arp::String>("path")));
this->FileList.push_back(file);
reader.ReadEndElement();
}
} // namespace MyComponent
データを読む
XMLConfigDocument
でクラスを使用できるようになりました クラスにデータをロードするための LoadConfig メソッドのクラス。
void MyComponent::LoadConfig() { // load project config here using namespace Arp::System::Commons; this->log.Info("LoadConfig"); // Fist argument has to match the XML root element name. // Our MyConfiguration instance this->config will be populated. Xml::XmlConfigDocument configDoc("MyConfigDocument", this->config); if (!Io::File::Exists(this->settingsPath)) { this->log.Error("Configuration file '{}' does not exist.", this->settingsPath); return; } try { configDoc.Load(this->settingsPath); } catch (const Arp::Exception& e) { this->log.Error(e.GetMessage()); throw InvalidConfigException(e.GetMessage()); } }
産業技術