File: Document.cpp

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (158 lines) | stat: -rw-r--r-- 3,363 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#include "Document.h"
#include "XPathException.h"

#include "itextstream.h"
#include <vector>
#include <fstream>

namespace xml
{

Document::Document()
{
    createDeclNode();
}

Document::Document(const std::string& filename)
{
    std::ifstream fileStream(filename);
    loadFromStream(fileStream);
}

Document::Document(std::istream& stream)
{
    loadFromStream(stream);
}

Document::Document(const Document& rhs)
: _parseResult(rhs._parseResult)
{
    std::lock_guard<std::mutex> lock(rhs._lock);

    _xmlDoc.reset(rhs._xmlDoc);
}

void Document::loadFromStream(std::istream& is)
{
    _parseResult = _xmlDoc.load(is);
    createDeclNode();
}

void Document::createDeclNode()
{
    pugi::xml_node decl = _xmlDoc.prepend_child(pugi::node_declaration);
    decl.append_attribute("version") = "1.0";
    decl.append_attribute("encoding") = "utf-8";
}

Document Document::create()
{
    return Document();
}

Document Document::clone(const Document& source)
{
    return Document(source);
}

Node Document::addTopLevelNode(const std::string& name)
{
    std::lock_guard<std::mutex> lock(_lock);

    _xmlDoc.remove_children();
    createDeclNode(); // remove_children also removes the decl
    auto node = _xmlDoc.append_child(name.c_str());

    return Node(this, node);
}

Node Document::getTopLevelNode() const
{
    std::lock_guard lock(_lock);

    if (!isValid())
        // Invalid Document, return a NULL node
        return Node(this);

    return Node(this, _xmlDoc.document_element());
}

void Document::importDocument(Document& other, Node& importNode)
{
    std::lock_guard<std::mutex> lock(_lock);

    if (!importNode.isValid()) {
        // invalid importnode
        return;
    }

    auto targetNode = importNode.getNodePtr();
    for (pugi::xml_node child: other._xmlDoc.children()) {
        targetNode.append_copy(child);
    }
}

void Document::copyNodes(const NodeList& nodeList)
{
    std::lock_guard<std::mutex> lock(_lock);

    if (!isValid()) {
        return; // is not Valid, place an assertion here?
    }

    // Copy the child nodes one by one
    for (auto node: nodeList) {
        _xmlDoc.document_element().append_copy(node.getNodePtr());
    }
}

bool Document::isValid() const
{
    return !_parseResult || _parseResult->status == pugi::status_ok;
}

// Evaluate an XPath expression and return matching Nodes.
NodeList Document::findXPath(const std::string& path) const
{
    std::lock_guard<std::mutex> lock(_lock);

    // Evaluate the XPath
    pugi::xpath_node_set nodes = _xmlDoc.select_nodes(path.c_str());

    // Construct the return vector. This may be empty if the provided XPath
    // expression does not identify any nodes.
    NodeList retval;
    for (pugi::xpath_node xpNode: nodes) {
        retval.emplace_back(this, xpNode.node());
    }
    return retval;
}

void Document::saveToStream(std::ostream& os) const
{
    _xmlDoc.save(os, "", pugi::format_raw, pugi::encoding_utf8);
}

void Document::saveToFile(const std::string& filename) const
{
    std::lock_guard<std::mutex> lock(_lock);

    std::ofstream fileStream(filename);
    saveToStream(fileStream);
}

std::string Document::saveToString() const
{
    std::lock_guard<std::mutex> lock(_lock);

    std::stringstream stream;
    saveToStream(stream);
    return stream.str();
}

std::mutex& Document::getLock() const
{
    return _lock;
}

}