1 | // |
---|---|
2 | // NodeIterator.cpp |
3 | // |
4 | // Library: XML |
5 | // Package: DOM |
6 | // Module: NodeIterator |
7 | // |
8 | // Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/DOM/NodeIterator.h" |
16 | #include "Poco/DOM/AbstractNode.h" |
17 | #include "Poco/DOM/NodeFilter.h" |
18 | #include "Poco/DOM/DOMException.h" |
19 | |
20 | |
21 | namespace Poco { |
22 | namespace XML { |
23 | |
24 | |
25 | NodeIterator::NodeIterator(Node* root, unsigned long whatToShow, NodeFilter* pFilter): |
26 | _pRoot(root), |
27 | _whatToShow(whatToShow), |
28 | _pFilter(pFilter), |
29 | _pCurrent(0) |
30 | { |
31 | } |
32 | |
33 | |
34 | NodeIterator::NodeIterator(const NodeIterator& iterator): |
35 | _pRoot(iterator._pRoot), |
36 | _whatToShow(iterator._whatToShow), |
37 | _pFilter(iterator._pFilter), |
38 | _pCurrent(iterator._pCurrent) |
39 | { |
40 | } |
41 | |
42 | |
43 | NodeIterator& NodeIterator::operator = (const NodeIterator& iterator) |
44 | { |
45 | if (&iterator != this) |
46 | { |
47 | _pRoot = iterator._pRoot; |
48 | _whatToShow = iterator._whatToShow; |
49 | _pFilter = iterator._pFilter; |
50 | _pCurrent = iterator._pCurrent; |
51 | } |
52 | return *this; |
53 | } |
54 | |
55 | |
56 | NodeIterator::~NodeIterator() |
57 | { |
58 | } |
59 | |
60 | |
61 | Node* NodeIterator::nextNode() |
62 | { |
63 | if (!_pRoot) throw DOMException(DOMException::INVALID_STATE_ERR); |
64 | |
65 | if (_pCurrent) |
66 | _pCurrent = next(); |
67 | else |
68 | _pCurrent = _pRoot; |
69 | while (_pCurrent && !accept(_pCurrent)) |
70 | _pCurrent = next(); |
71 | return _pCurrent; |
72 | } |
73 | |
74 | |
75 | Node* NodeIterator::previousNode() |
76 | { |
77 | if (!_pRoot) throw DOMException(DOMException::INVALID_STATE_ERR); |
78 | |
79 | if (_pCurrent) |
80 | _pCurrent = previous(); |
81 | else |
82 | _pCurrent = last(); |
83 | while (_pCurrent && !accept(_pCurrent)) |
84 | _pCurrent = previous(); |
85 | return _pCurrent; |
86 | } |
87 | |
88 | |
89 | void NodeIterator::detach() |
90 | { |
91 | _pRoot = 0; |
92 | _pCurrent = 0; |
93 | } |
94 | |
95 | |
96 | bool NodeIterator::accept(Node* pNode) const |
97 | { |
98 | bool accept = false; |
99 | switch (pNode->nodeType()) |
100 | { |
101 | case Node::ELEMENT_NODE: |
102 | accept = (_whatToShow & NodeFilter::SHOW_ELEMENT) != 0; break; |
103 | case Node::ATTRIBUTE_NODE: |
104 | accept = (_whatToShow & NodeFilter::SHOW_ATTRIBUTE) != 0; break; |
105 | case Node::TEXT_NODE: |
106 | accept = (_whatToShow & NodeFilter::SHOW_TEXT) != 0; break; |
107 | case Node::CDATA_SECTION_NODE: |
108 | accept = (_whatToShow & NodeFilter::SHOW_CDATA_SECTION) != 0; break; |
109 | case Node::ENTITY_REFERENCE_NODE: |
110 | accept = (_whatToShow & NodeFilter::SHOW_ENTITY_REFERENCE) != 0; break; |
111 | case Node::ENTITY_NODE: |
112 | accept = (_whatToShow & NodeFilter::SHOW_ENTITY) != 0; break; |
113 | case Node::PROCESSING_INSTRUCTION_NODE: |
114 | accept = (_whatToShow & NodeFilter::SHOW_PROCESSING_INSTRUCTION) != 0; break; |
115 | case Node::COMMENT_NODE: |
116 | accept = (_whatToShow & NodeFilter::SHOW_COMMENT) != 0; break; |
117 | case Node::DOCUMENT_NODE: |
118 | accept = (_whatToShow & NodeFilter::SHOW_DOCUMENT) != 0; break; |
119 | case Node::DOCUMENT_TYPE_NODE: |
120 | accept = (_whatToShow & NodeFilter::SHOW_DOCUMENT_TYPE) != 0; break; |
121 | case Node::DOCUMENT_FRAGMENT_NODE: |
122 | accept = (_whatToShow & NodeFilter::SHOW_DOCUMENT_FRAGMENT) != 0; break; |
123 | case Node::NOTATION_NODE: |
124 | accept = (_whatToShow & NodeFilter::SHOW_NOTATION) != 0; break; |
125 | } |
126 | if (accept && _pFilter) |
127 | accept = _pFilter->acceptNode(pNode) == NodeFilter::FILTER_ACCEPT; |
128 | return accept; |
129 | } |
130 | |
131 | |
132 | Node* NodeIterator::next() const |
133 | { |
134 | Node* pNext = _pCurrent->firstChild(); |
135 | if (pNext) return pNext; |
136 | pNext = _pCurrent; |
137 | while (pNext && pNext != _pRoot) |
138 | { |
139 | Node* pSibling = pNext->nextSibling(); |
140 | if (pSibling) return pSibling; |
141 | pNext = pNext->parentNode(); |
142 | } |
143 | return 0; |
144 | } |
145 | |
146 | |
147 | Node* NodeIterator::previous() const |
148 | { |
149 | if (_pCurrent == _pRoot) return 0; |
150 | Node* pPrev = _pCurrent->previousSibling(); |
151 | while (pPrev) |
152 | { |
153 | Node* pLastChild = pPrev->lastChild(); |
154 | if (pLastChild) |
155 | pPrev = pLastChild; |
156 | else |
157 | return pPrev; |
158 | } |
159 | return _pCurrent->parentNode(); |
160 | } |
161 | |
162 | |
163 | Node* NodeIterator::last() |
164 | { |
165 | _pCurrent = _pRoot; |
166 | Node* pLast = 0; |
167 | while (_pCurrent) |
168 | { |
169 | pLast = _pCurrent; |
170 | _pCurrent = next(); |
171 | } |
172 | return pLast; |
173 | } |
174 | |
175 | |
176 | } } // namespace Poco::XML |
177 |