Skip to content

Commit a3e0951

Browse files
committed
Migrate from QDomDocument to QXmlStreamReader
QDomDocument is deprecated in Qt6 and required a separate Qt module (QtXml). Qt docs recommend to use QXmlStreamReader instead, which is even part of QtCore.
1 parent 9bce095 commit a3e0951

File tree

6 files changed

+70
-50
lines changed

6 files changed

+70
-50
lines changed

CMakeLists.txt

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ project(parseagle
1111

1212
# If Qt version is not explicitly specified, automatically determine it
1313
if(NOT PARSEAGLE_QT_MAJOR_VERSION)
14-
find_package(Qt NAMES Qt5 Qt6 REQUIRED COMPONENTS Core Xml)
14+
find_package(Qt NAMES Qt5 Qt6 REQUIRED COMPONENTS Core)
1515
set(PARSEAGLE_QT_MAJOR_VERSION ${Qt_VERSION_MAJOR})
1616
endif()
1717
set(PARSEAGLE_QT "Qt${PARSEAGLE_QT_MAJOR_VERSION}")
@@ -26,7 +26,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
2626
set(CMAKE_CXX_EXTENSIONS OFF)
2727

2828
# Find required Qt packages
29-
find_package(${PARSEAGLE_QT} REQUIRED COMPONENTS Core Xml)
29+
find_package(${PARSEAGLE_QT} REQUIRED COMPONENTS Core)
3030
message(STATUS "Building parseagle with Qt ${${PARSEAGLE_QT}_VERSION}")
3131

3232
# Export library
@@ -119,11 +119,7 @@ add_library(parseagle STATIC
119119
parseagle/symbol/pin.h
120120
parseagle/symbol/symbol.h
121121
)
122-
target_link_libraries(parseagle
123-
# Qt
124-
${PARSEAGLE_QT}::Core
125-
${PARSEAGLE_QT}::Xml
126-
)
122+
target_link_libraries(parseagle ${PARSEAGLE_QT}::Core)
127123
target_include_directories(parseagle INTERFACE "${CMAKE_CURRENT_SOURCE_DIR}")
128124

129125
# Alias to namespaced variant

parseagle/board/board.cpp

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,8 @@ Board::~Board() noexcept
2828

2929
void Board::load(const QByteArray& content, QStringList* errors)
3030
{
31-
QDomDocument doc;
32-
doc.implementation().setInvalidDataPolicy(QDomImplementation::ReturnNullNode);
33-
QString errMsg;
34-
if (!doc.setContent(content, &errMsg)) {
35-
throw std::runtime_error(
36-
"Error while parsing EAGLE board: " + errMsg.toStdString());
37-
}
38-
DomElement root(doc.documentElement());
39-
DomElement drawing = root.getFirstChild("drawing");
31+
const DomElement root = DomElement::parse(content);
32+
const DomElement drawing = root.getFirstChild("drawing");
4033

4134
if (drawing.hasChild("grid")) {
4235
mGrid = Grid(drawing.getFirstChild("grid"));

parseagle/common/domelement.cpp

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,68 @@
33

44
namespace parseagle {
55

6-
DomElement::DomElement(const QDomElement& root)
6+
DomElement::DomElement(QXmlStreamReader& reader)
77
{
8-
if (root.isNull()) {
9-
throw std::runtime_error("Invalid XML node!");
8+
mName = reader.name().toString();
9+
for (const QXmlStreamAttribute& attr : reader.attributes()) {
10+
mAttributes.insert(attr.name().toString(), attr.value().toString());
1011
}
1112

12-
mName = root.tagName();
13-
mText = root.text();
14-
15-
QDomNamedNodeMap map = root.attributes();
16-
for (int i = 0; i < map.count(); i++) {
17-
mAttributes.insert(map.item(i).nodeName(), map.item(i).nodeValue());
13+
while (!reader.atEnd()) {
14+
reader.readNext();
15+
if (reader.isCharacters()) {
16+
mText.append(reader.text().toString());
17+
} else if (reader.isStartElement()) {
18+
mChilds.append(DomElement(reader));
19+
} else if (reader.isEndElement()) {
20+
break;
21+
}
1822
}
1923

20-
for (QDomElement c = root.firstChildElement(); !c.isNull(); c = c.nextSiblingElement()) {
21-
mChilds.append(DomElement(c));
24+
if (reader.hasError()) {
25+
const QString err = "Failed to parse XML: " + reader.errorString();
26+
throw std::runtime_error(err.toStdString());
2227
}
2328
}
2429

2530
DomElement::~DomElement() noexcept
2631
{
2732
}
2833

34+
DomElement DomElement::parse(QXmlStreamReader& reader)
35+
{
36+
while (!reader.atEnd()) {
37+
reader.readNext();
38+
if (reader.isStartElement()) {
39+
break;
40+
}
41+
}
42+
if (reader.hasError() || (!reader.isStartElement())) {
43+
const QString err = "Failed to find XML root element: " + reader.errorString();
44+
throw std::runtime_error(err.toStdString());
45+
}
46+
const DomElement root(reader);
47+
if (reader.hasError() || (!reader.isEndElement())) {
48+
const QString err = "XML file seems incomplete: " + reader.errorString();
49+
throw std::runtime_error(err.toStdString());
50+
}
51+
return root;
52+
}
53+
54+
DomElement DomElement::parse(const QString& data)
55+
{
56+
QXmlStreamReader reader;
57+
reader.addData(data);
58+
return parse(reader);
59+
}
60+
61+
DomElement DomElement::parse(const QByteArray& data)
62+
{
63+
QXmlStreamReader reader;
64+
reader.addData(data);
65+
return parse(reader);
66+
}
67+
2968
QString DomElement::getAttributeAsString(const QString& name) const
3069
{
3170
if (mAttributes.contains(name)) {
@@ -37,7 +76,8 @@ QString DomElement::getAttributeAsString(const QString& name) const
3776
}
3877
}
3978

40-
bool DomElement::getAttributeAsBool(const QString& name) const {
79+
bool DomElement::getAttributeAsBool(const QString& name) const
80+
{
4181
const QString value = getAttributeAsString(name);
4282
if (value == "yes") {
4383
return true;

parseagle/common/domelement.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33

44
#include <memory>
55
#include <QtCore>
6-
#include <QtXml/QtXml>
76

87
namespace parseagle {
98

@@ -13,9 +12,13 @@ class DomElement final
1312

1413
// Constructors / Destructor
1514
DomElement() = delete;
16-
explicit DomElement(const QDomElement& root);
1715
~DomElement() noexcept;
1816

17+
// Parsers
18+
static DomElement parse(QXmlStreamReader& reader);
19+
static DomElement parse(const QString& data);
20+
static DomElement parse(const QByteArray& data);
21+
1922
// Getters
2023
const QString& getTagName() const noexcept {return mName;}
2124
const QString& getText() const noexcept {return mText;}
@@ -30,6 +33,8 @@ class DomElement final
3033

3134

3235
private:
36+
explicit DomElement(QXmlStreamReader& reader);
37+
3338
QString mName;
3439
QString mText;
3540
QHash<QString, QString> mAttributes;

parseagle/library.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,16 +33,9 @@ Library::~Library() noexcept
3333

3434
void Library::load(const QByteArray& content, QStringList* errors)
3535
{
36-
QDomDocument doc;
37-
doc.implementation().setInvalidDataPolicy(QDomImplementation::ReturnNullNode);
38-
QString errMsg;
39-
if (!doc.setContent(content, &errMsg)) {
40-
throw std::runtime_error(
41-
"Error while parsing EAGLE library: " + errMsg.toStdString());
42-
}
43-
DomElement root(doc.documentElement());
44-
DomElement drawing = root.getFirstChild("drawing");
45-
DomElement library = drawing.getFirstChild("library");
36+
const DomElement root = DomElement::parse(content);
37+
const DomElement drawing = root.getFirstChild("drawing");
38+
const DomElement library = drawing.getFirstChild("library");
4639
load(library, errors);
4740
}
4841

parseagle/schematic/schematic.cpp

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,14 @@ Schematic::~Schematic() noexcept
2727
}
2828

2929
void Schematic::load(const QByteArray& content, QStringList* errors) {
30-
QDomDocument doc;
31-
doc.implementation().setInvalidDataPolicy(QDomImplementation::ReturnNullNode);
32-
QString errMsg;
33-
if (!doc.setContent(content, &errMsg)) {
34-
throw std::runtime_error(
35-
"Error while parsing EAGLE schematic: " + errMsg.toStdString());
36-
}
37-
DomElement root(doc.documentElement());
38-
DomElement drawing = root.getFirstChild("drawing");
30+
const DomElement root = DomElement::parse(content);
31+
const DomElement drawing = root.getFirstChild("drawing");
3932

4033
if (drawing.hasChild("grid")) {
4134
mGrid = Grid(drawing.getFirstChild("grid"));
4235
}
4336

44-
DomElement schematic = drawing.getFirstChild("schematic");
37+
const DomElement schematic = drawing.getFirstChild("schematic");
4538
if (schematic.hasChild("description")) {
4639
mDescription = schematic.getFirstChild("description").getText();
4740
}

0 commit comments

Comments
 (0)