1//
2// ElementsByTagNameList.cpp
3//
4// Library: XML
5// Package: DOM
6// Module: DOM
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/ElementsByTagNameList.h"
16#include "Poco/DOM/Node.h"
17#include "Poco/DOM/Document.h"
18#include <climits>
19
20
21namespace Poco {
22namespace XML {
23
24
25ElementsByTagNameList::ElementsByTagNameList(const Node* pParent, const XMLString& name):
26 _pParent(pParent),
27 _name(name),
28 _count(0)
29{
30 poco_check_ptr (pParent);
31
32 _pParent->duplicate();
33}
34
35
36ElementsByTagNameList::~ElementsByTagNameList()
37{
38 _pParent->release();
39}
40
41
42Node* ElementsByTagNameList::item(unsigned long index) const
43{
44 _count = 0;
45 return find(_pParent, index);
46}
47
48
49unsigned long ElementsByTagNameList::length() const
50{
51 _count = 0;
52 find(_pParent, ULONG_MAX);
53 return _count;
54}
55
56
57namespace
58{
59 static const XMLString asterisk = toXMLString("*");
60}
61
62
63Node* ElementsByTagNameList::find(const Node* pParent, unsigned long index) const
64{
65 if (!pParent) return 0;
66
67 // preorder search
68 Node* pCur = pParent->firstChild();
69 while (pCur)
70 {
71 if (pCur->nodeType() == Node::ELEMENT_NODE && (_name == asterisk || pCur->nodeName() == _name))
72 {
73 if (_count == index) return pCur;
74 _count++;
75 }
76 Node* pNode = find(pCur, index);
77 if (pNode) return pNode;
78 pCur = pCur->nextSibling();
79 }
80 return pCur;
81}
82
83
84void ElementsByTagNameList::autoRelease()
85{
86 _pParent->ownerDocument()->autoReleasePool().add(this);
87}
88
89
90ElementsByTagNameListNS::ElementsByTagNameListNS(const Node* pParent, const XMLString& namespaceURI, const XMLString& localName):
91 _pParent(pParent),
92 _localName(localName),
93 _namespaceURI(namespaceURI),
94 _count(0)
95{
96 poco_check_ptr (pParent);
97
98 _pParent->duplicate();
99}
100
101
102
103ElementsByTagNameListNS::~ElementsByTagNameListNS()
104{
105 _pParent->release();
106}
107
108
109Node* ElementsByTagNameListNS::item(unsigned long index) const
110{
111 _count = 0;
112 return find(_pParent, index);
113}
114
115
116unsigned long ElementsByTagNameListNS::length() const
117{
118 _count = 0;
119 find(_pParent, ULONG_MAX);
120 return _count;
121}
122
123
124Node* ElementsByTagNameListNS::find(const Node* pParent, unsigned long index) const
125{
126 if (!pParent) return 0;
127
128 // preorder search
129 Node* pCur = pParent->firstChild();
130 while (pCur)
131 {
132 if (pCur->nodeType() == Node::ELEMENT_NODE && (_localName == asterisk || pCur->localName() == _localName) && (_namespaceURI == asterisk || pCur->namespaceURI() == _namespaceURI))
133 {
134 if (_count == index) return pCur;
135 _count++;
136 }
137 Node* pNode = find(pCur, index);
138 if (pNode) return pNode;
139 pCur = pCur->nextSibling();
140 }
141 return pCur;
142}
143
144
145void ElementsByTagNameListNS::autoRelease()
146{
147 _pParent->ownerDocument()->autoReleasePool().add(this);
148}
149
150
151} } // namespace Poco::XML
152