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
21namespace Poco {
22namespace XML {
23
24
25NodeIterator::NodeIterator(Node* root, unsigned long whatToShow, NodeFilter* pFilter):
26 _pRoot(root),
27 _whatToShow(whatToShow),
28 _pFilter(pFilter),
29 _pCurrent(0)
30{
31}
32
33
34NodeIterator::NodeIterator(const NodeIterator& iterator):
35 _pRoot(iterator._pRoot),
36 _whatToShow(iterator._whatToShow),
37 _pFilter(iterator._pFilter),
38 _pCurrent(iterator._pCurrent)
39{
40}
41
42
43NodeIterator& 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
56NodeIterator::~NodeIterator()
57{
58}
59
60
61Node* 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
75Node* 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
89void NodeIterator::detach()
90{
91 _pRoot = 0;
92 _pCurrent = 0;
93}
94
95
96bool 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
132Node* 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
147Node* 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
163Node* 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