1//
2// NamespaceSupport.h
3//
4// Library: XML
5// Package: SAX
6// Module: SAX
7//
8// Namespace support for SAX2.
9//
10// Copyright (c) 2004-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef SAX_NamespaceSupport_INCLUDED
18#define SAX_NamespaceSupport_INCLUDED
19
20
21#include "Poco/XML/XML.h"
22#include "Poco/XML/XMLString.h"
23#include <set>
24#include <map>
25#include <vector>
26
27
28namespace Poco {
29namespace XML {
30
31
32class XML_API NamespaceSupport
33 /// Encapsulate Namespace logic for use by SAX drivers.
34 /// This class encapsulates the logic of Namespace processing:
35 /// it tracks the declarations currently in force for each context and
36 /// automatically processes qualified XML 1.0 names into their Namespace
37 /// parts; it can also be used in reverse for generating
38 /// XML 1.0 from Namespaces.
39 /// Namespace support objects are reusable, but the reset method
40 /// must be invoked between each session.
41{
42public:
43 typedef std::set<XMLString> PrefixSet;
44
45 NamespaceSupport();
46 /// Creates a NamespaceSupport object.
47
48 ~NamespaceSupport();
49 /// Destroys a NamespaceSupport object.
50
51 bool declarePrefix(const XMLString& prefix, const XMLString& namespaceURI);
52 /// Declare a Namespace prefix. All prefixes must be declared before they are
53 /// referenced. For example, a SAX driver (parser) would scan an element's attributes
54 /// in two passes: first for namespace declarations, then a second pass using
55 /// processName() to interpret prefixes against (potentially redefined) prefixes.
56 ///
57 /// This method declares a prefix in the current Namespace context; the prefix
58 /// will remain in force until this context is popped, unless it is shadowed
59 /// in a descendant context.
60 ///
61 /// To declare the default element Namespace, use the empty string as the prefix.
62 ///
63 /// Note that you must not declare a prefix after you've pushed and popped another
64 /// Namespace context, or treated the declarations phase as complete by processing
65 /// a prefixed name.
66 ///
67 /// Returns true if the prefix was legal, false otherwise.
68
69 bool undeclarePrefix(const XMLString& prefix);
70 /// Remove the given namespace prefix.
71
72 void getDeclaredPrefixes(PrefixSet& prefixes) const;
73 /// Return an enumeration of all prefixes declared in this context.
74 ///
75 /// The empty (default) prefix will be included in this enumeration; note that
76 /// this behaviour differs from that of getPrefix() and getPrefixes().
77
78 const XMLString& getPrefix(const XMLString& namespaceURI) const;
79 /// Return one of the prefixes mapped to a Namespace URI.
80 ///
81 /// If more than one prefix is currently mapped to the same URI, this method
82 /// will make an arbitrary selection; if you want all of the prefixes, use the
83 /// getPrefixes() method instead.
84
85 bool isMapped(const XMLString& namespaceURI) const;
86 /// Returns true if the given namespaceURI has been mapped to a prefix,
87 /// false otherwise.
88
89 void getPrefixes(PrefixSet& prefixes) const;
90 /// Return an enumeration of all prefixes whose declarations are active in the
91 /// current context. This includes declarations from parent contexts that have
92 /// not been overridden.
93 ///
94 /// Note: if there is a default prefix, it will not be returned in this enumeration;
95 /// check for the default prefix using the getURI with an argument of "".
96
97 void getPrefixes(const XMLString& namespaceURI, PrefixSet& prefixes) const;
98 /// Return an enumeration of all prefixes for a given URI whose declarations
99 /// are active in the current context. This includes declarations from parent
100 /// contexts that have not been overridden.
101 ///
102 /// This method returns prefixes mapped to a specific Namespace URI. The xml:
103 /// prefix will be included. If you want only one prefix that's mapped to the
104 /// Namespace URI, and you don't care which one you get, use the getPrefix() method
105 /// instead.
106 ///
107 /// Note: the empty (default) prefix is never included in this enumeration;
108 /// to check for the presence of a default Namespace, use the getURI() method
109 /// with an argument of "".
110
111 const XMLString& getURI(const XMLString& prefix) const;
112 /// Look up a prefix and get the currently-mapped Namespace URI.
113 ///
114 /// This method looks up the prefix in the current context. Use the empty string
115 /// ("") for the default Namespace.
116
117 void pushContext();
118 /// Start a new Namespace context. The new context will automatically inherit
119 /// the declarations of its parent context, but it will also keep track of which
120 /// declarations were made within this context.
121 ///
122 /// Event callback code should start a new context once per element. This means
123 /// being ready to call this in either of two places. For elements that don't
124 /// include namespace declarations, the ContentHandler::startElement() callback
125 /// is the right place. For elements with such a declaration, it'd done in the
126 /// first ContentHandler::startPrefixMapping() callback. A boolean flag can be
127 /// used to track whether a context has been started yet. When either of those
128 /// methods is called, it checks the flag to see if a new context needs to be
129 /// started. If so, it starts the context and sets the flag. After
130 /// ContentHandler::startElement() does that, it always clears the flag.
131 ///
132 /// Normally, SAX drivers would push a new context at the beginning of each
133 /// XML element. Then they perform a first pass over the attributes to process
134 /// all namespace declarations, making ContentHandler::startPrefixMapping() callbacks.
135 /// Then a second pass is made, to determine the namespace-qualified names for
136 /// all attributes and for the element name. Finally all the information for
137 /// the ContentHandler::startElement() callback is available, so it can then
138 /// be made.
139 ///
140 /// The Namespace support object always starts with a base context already in
141 /// force: in this context, only the "xml" prefix is declared.
142
143 void popContext();
144 /// Revert to the previous Namespace context.
145 ///
146 /// Normally, you should pop the context at the end of each XML element. After
147 /// popping the context, all Namespace prefix mappings that were previously
148 /// in force are restored.
149 ///
150 /// You must not attempt to declare additional Namespace prefixes after popping
151 /// a context, unless you push another context first.
152
153 bool processName(const XMLString& qname, XMLString& namespaceURI, XMLString& localName, bool isAttribute) const;
154 /// Process a raw XML 1.0 name.
155 /// This method processes a raw XML 1.0 name in the current context
156 /// by removing the prefix and looking it up among the
157 /// prefixes currently declared. The result will be returned in
158 /// namespaceURI and localName.
159 /// If the raw name has a prefix that has not been declared, then the return
160 /// value will be false, otherwise true.
161 ///
162 /// Note that attribute names are processed differently than element names:
163 /// an unprefixed element name will receive the
164 /// default Namespace (if any), while an unprefixed attribute name will not.
165
166 void reset();
167 /// Reset this Namespace support object for reuse.
168 ///
169 /// It is necessary to invoke this method before reusing the Namespace support
170 /// object for a new session. If namespace declaration URIs are to be supported,
171 /// that flag must also be set to a non-default value.
172 /// Reset this Namespace support object for reuse.
173
174 static const XMLString XML_NAMESPACE;
175 static const XMLString XML_NAMESPACE_PREFIX;
176 static const XMLString XMLNS_NAMESPACE;
177 static const XMLString XMLNS_NAMESPACE_PREFIX;
178
179private:
180 NamespaceSupport(const NamespaceSupport&);
181 NamespaceSupport& operator = (const NamespaceSupport&);
182
183 typedef std::map<XMLString, XMLString> Context;
184 typedef std::vector<Context> ContextVec;
185
186 ContextVec _contexts;
187
188 static const XMLString EMPTY_STRING;
189};
190
191
192} } // namespace Poco::XML
193
194
195#endif // SAX_NamespaceSupport_INCLUDED
196