산업 제조
산업용 사물 인터넷 | 산업자재 | 장비 유지 보수 및 수리 | 산업 프로그래밍 |
home  MfgRobots >> 산업 제조 >  >> Manufacturing Technology >> 산업기술

PLCnext에서 IXMLSerializable로 XML로부터 C++ 클래스 채우기

요약

PLCnext 공통 클래스에 XML 직렬화에 대한 내장 지원이 있다는 것을 알고 계셨나요? 이 문서에서는 IXmlSerializable 인터페이스를 사용하여 C++ 클래스의 데이터를 채우는 방법을 보여줍니다.

인터페이스 설명은 PLCnext 공통 클래스의 API 문서에서 찾을 수 있습니다.

요구 사항

이 문서는 다음 설정으로 작성되었습니다:

PLCnext 펌웨어: 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 인터페이스
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) {
  // 연산 없음.
  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() {
  // 프로젝트 설정 로드
  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("구성 파일 '{}'이(가) 존재하지 않습니다.", this->settingsPath);
    return;
  }
  try {
    configDoc.Load(this->settingsPath);
  } catch (const Arp::Exception& e) {
    this->log.Error(e.GetMessage());
    throw InvalidConfigException(e.GetMessage());
  }
}

산업기술

  1. SPICE와 명령줄 인터페이스(CLI) 사용법
  2. 기술이 제조업을 혁신하는 방식: 3D 프린팅에서 디지털 트윈까지
  3. Java BufferedReader 마스터하기: 효율적 캐릭터 스트림 처리
  4. java.io로 Java 파일 작업 마스터하기 – 생성, 읽기, 쓰기 및 삭제
  5. Java 인터페이스 vs 추상 클래스: 올바른 추상화 선택 가이드
  6. 자바 인터페이스 이해하기: 정의, 용도, 모범 사례
  7. 방폭 모터 선정 완벽 가이드: 분류, 인증, AIT까지
  8. 제조용 다이 종류: 스탬핑, 드로잉, 주조 다이 설명
  9. PCB 테스트 포인트 활용으로 테스트 효율성 및 생산성 향상
  10. 자동화가 제조를 변화시키는 방식: 효율성 증대와 비용 절감