Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Промышленные технологии

Заполнение C++ класса из XML с использованием IXMLSerializable в PLCnext

Аннотация

Знаете ли вы, что в PLCnext Common Classes есть встроенная поддержка XML-сериализации? Эта статья показывает, как использовать интерфейс IXmlSerializable для заполнения данных в C++ классе.

Описание интерфейса можно найти в API документации PLCnext Common Classes.

Требования

Статья написана со следующей настройкой:

PLCnext Firmware: 2020.6 LTS
PLCnext C++ SDK для 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. Определенные переменные окружения Arp можно найти в файле настроек устройства на целевом устройстве /etc/plcnext/Device.acf.settings.

Чтобы читать данные из 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;

    // Данные
  public:
    Arp::String DnsName{""};
    std::vector<Arp::String> FileList;

    // Вспомогательные методы
  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) {
    // Используем 'context.ResolvePath' для замены плейсхолдеров в пути.
    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");
  // Первый аргумент должен соответствовать имени корневого XML элемента.
  // Наш экземпляр MyConfiguration this->config будет заполнен.
  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. Как технологии трансформируют производство: от 3D-печати к цифровым двойникам
  3. Освоение Java BufferedReader: эффективная обработка символьных потоков
  4. Мастерство файловых операций в Java с java.io: создание, чтение, запись и удаление
  5. Интерфейс vs Абстрактный класс в Java: Как выбрать правильную абстракцию
  6. Интерфейсы в Java: определение, использование и лучшие практики
  7. Выбор правильного взрывозащищенного двигателя: всеобъемлющее руководство
  8. Типы штампов в производстве: штамповка, вытягивание и литье
  9. Как тестовые точки улучшают тестирование печатных плат и производственную эффективность
  10. Как автоматизация трансформирует производство: Повышение эффективности и сокращение затрат