NamespaceSupport.h 7.8 KB

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