亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 工业技术

在 PLCnext 中使用 IXMLSerializable 从 XML 填充 C++ 类

摘要

您知道 PLCnext Common Classes 内置支持 XML 序列化吗?本文展示如何使用 IXmlSerializable 接口填充 C++ 类数据。

接口描述见 PLCnext Common Classes 的 API 文档。

要求

本文基于以下环境编写:

PLCnext Firmware: 2020.6 LTS PLCnext C++ SDK for Linux 64 Bit 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。可在目标设备 /etc/plcnext/Device.acf.settings 设置文件中找到定义的 Arp 环境变量。

要从 XML 文件读取数据,必须为类实现 IXMLSerializable 接口。为简单起见,类仅有两个数据元素:DNS 名称和文件路径向量。

#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

读取数据

现可在 LoadConfig 方法中用 XMLConfigDocument 类加载数据到类中。

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()); } }

工业技术

  1. SPICE 命令行界面使用详解
  2. 数字孪生如何革新制造业:收益、应用与ROI
  3. 技术如何变革制造业:从3D打印到数字孪生
  4. 防爆电机选型全攻略:分级分组、认证合规与自燃温度匹配五步法
  5. 制造业模具类型详解:冲压、拉拔、铸造模具全解析
  6. 测试点如何提升PCB测试与生产效率
  7. 自动化如何重塑制造业:提效降本的关键路径
  8. 工业 4.0 中增强现实 (AR) 的优势
  9. 掌握 Java BufferedReader:高效字符流处理实战指南
  10. 掌握 Java 文件操作:java.io 包下的创建、读取、写入与删除
  11. Java 接口 vs 抽象类:如何选择合适的抽象方式
  12. Java 接口全解析:定义契约、默认方法、多实现与标记接口