Branch data Line data Source code
1 : : #pragma once
2 : :
3 : : #include <QDomDocument>
4 : : #include <QDomElement>
5 : : #include <QDomNodeList>
6 : : #include <QString>
7 : :
8 : : // ═══════════════════════════════════════════════════════
9 : : // Shared DAV XML helpers (Sprint 32 – T-331)
10 : : // Extracted from CardDavClient.cpp for reuse in CalDavClient.
11 : : // ═══════════════════════════════════════════════════════
12 : :
13 : : namespace DavXmlHelper {
14 : :
15 : : /// Find child elements by local name, ignoring namespace prefix.
16 : : /// Uses localName() comparison which is namespace-prefix-agnostic.
17 : 206 : inline QDomNodeList findElementsByLocalName(const QDomElement &parent,
18 : : const QString &localName) {
19 : : // Fast path: try unprefixed tag name
20 [ + - ]: 206 : QDomNodeList nodes = parent.elementsByTagName(localName);
21 [ + - + + ]: 206 : if (!nodes.isEmpty())
22 : 6 : return nodes;
23 : :
24 : : // Namespace-agnostic: walk all descendants, match by localName()
25 [ + - ]: 200 : QDomNodeList all = parent.elementsByTagName(QStringLiteral("*"));
26 : : // Qt doesn't let us build a QDomNodeList, so we use the fast path with
27 : : // known prefixes as well, then fall back to manual iteration
28 : : static const QString prefixes[] = {
29 : 8 : QStringLiteral("d:"), QStringLiteral("D:"),
30 : 8 : QStringLiteral("card:"), QStringLiteral("C:"),
31 : 8 : QStringLiteral("cs:"), QStringLiteral("cr:"),
32 : 8 : QStringLiteral("cal:"), QStringLiteral("c:"),
33 : 8 : QStringLiteral("apple:"),
34 [ + + + - ]: 307 : };
35 [ + + ]: 784 : for (const auto &prefix : prefixes) {
36 [ + - + - : 753 : nodes = parent.elementsByTagName(prefix + localName);
+ - ]
37 [ + - + + ]: 753 : if (!nodes.isEmpty())
38 : 169 : return nodes;
39 : : }
40 : 31 : return nodes; // empty
41 : 200 : }
42 : :
43 : : /// Find the first element by local name using namespace-agnostic traversal.
44 : : /// This handles any arbitrary namespace prefix (x1:, ns0:, etc.).
45 : : /// Note: the documents here are parsed WITHOUT namespace processing, so
46 : : /// QDomElement::localName() is always empty — the local name must be
47 : : /// derived from tagName() by stripping the prefix. QDom also does not
48 : : /// support the DOM "*" wildcard, so the fallback walks children manually.
49 : 69 : inline QDomElement findFirstElementByLocalName(const QDomElement &parent,
50 : : const QString &localName) {
51 : : // Fast path: unprefixed
52 [ + - ]: 69 : QDomNodeList nodes = parent.elementsByTagName(localName);
53 [ + - + + ]: 69 : if (!nodes.isEmpty())
54 [ + - + - ]: 4 : return nodes.at(0).toElement();
55 : :
56 : : // Depth-first walk comparing the tag name after the prefix
57 [ + - + - : 109 : for (QDomElement el = parent.firstChildElement(); !el.isNull();
+ + ]
58 [ + - + - ]: 44 : el = el.nextSiblingElement()) {
59 [ + - ]: 60 : const QString tag = el.tagName();
60 [ + - + + ]: 60 : if (tag.mid(tag.indexOf(QLatin1Char(':')) + 1) == localName)
61 [ + - ]: 6 : return el;
62 [ + - ]: 54 : QDomElement deep = findFirstElementByLocalName(el, localName);
63 [ + - + + ]: 54 : if (!deep.isNull())
64 [ + - ]: 10 : return deep;
65 [ + + + + : 135 : }
+ + ]
66 [ + - ]: 49 : return {};
67 : 69 : }
68 : :
69 : : /// Same but for QDomDocument root level.
70 : 72 : inline QDomNodeList findElementsByLocalNameDoc(QDomDocument &doc,
71 : : const QString &localName) {
72 : 72 : QDomNodeList nodes = doc.elementsByTagName(localName);
73 [ + - + + ]: 72 : if (!nodes.isEmpty())
74 : 5 : return nodes;
75 : :
76 : : static const QString prefixes[] = {
77 : 7 : QStringLiteral("d:"), QStringLiteral("D:"),
78 : 7 : QStringLiteral("card:"), QStringLiteral("C:"),
79 : 7 : QStringLiteral("cs:"), QStringLiteral("cr:"),
80 : 7 : QStringLiteral("cal:"), QStringLiteral("c:"),
81 : 7 : QStringLiteral("apple:"),
82 [ + + + - ]: 130 : };
83 [ + + ]: 241 : for (const auto &prefix : prefixes) {
84 [ + - + - : 224 : nodes = doc.elementsByTagName(prefix + localName);
+ - ]
85 [ + - + + ]: 224 : if (!nodes.isEmpty())
86 : 50 : return nodes;
87 : : }
88 : 17 : return nodes;
89 : 0 : }
90 : :
91 : : } // namespace DavXmlHelper
|