GDataXMLNode.h 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /* Modifications for HTML parser support:
  2. * Copyright (c) 2011 Simon Grätzer simon@graetzer.org
  3. *
  4. * Copyright (c) 2008 Google Inc.
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. // These node, element, and document classes implement a subset of the methods
  19. // provided by NSXML. While NSXML behavior is mimicked as much as possible,
  20. // there are important differences.
  21. //
  22. // The biggest difference is that, since this is based on libxml2, there
  23. // is no retain model for the underlying node data. Rather than copy every
  24. // node obtained from a parse tree (which would have a substantial memory
  25. // impact), we rely on weak references, and it is up to the code that
  26. // created a document to retain it for as long as any
  27. // references rely on nodes inside that document tree.
  28. #import <Foundation/Foundation.h>
  29. // libxml includes require that the target Header Search Paths contain
  30. //
  31. // /usr/include/libxml2
  32. //
  33. // and Other Linker Flags contain
  34. //
  35. // -lxml2
  36. #import <libxml/tree.h>
  37. #import <libxml/parser.h>
  38. #import <libxml/xmlstring.h>
  39. #import <libxml/HTMLparser.h>
  40. #import <libxml/xpath.h>
  41. #import <libxml/xpathInternals.h>
  42. #if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_4) || defined(GDATA_TARGET_NAMESPACE)
  43. // we need NSInteger for the 10.4 SDK, or we're using target namespace macros
  44. #import "GDataDefines.h"
  45. #endif
  46. #undef _EXTERN
  47. #undef _INITIALIZE_AS
  48. #ifdef GDATAXMLNODE_DEFINE_GLOBALS
  49. #define _EXTERN
  50. #define _INITIALIZE_AS(x) =x
  51. #else
  52. #if defined(__cplusplus)
  53. #define _EXTERN extern "C"
  54. #else
  55. #define _EXTERN extern
  56. #endif
  57. #define _INITIALIZE_AS(x)
  58. #endif
  59. // when no namespace dictionary is supplied for XPath, the default namespace
  60. // for the evaluated tree is registered with the prefix _def_ns
  61. _EXTERN const char* kGDataXMLXPathDefaultNamespacePrefix _INITIALIZE_AS("_def_ns");
  62. // Nomenclature for method names:
  63. //
  64. // Node = GData node
  65. // XMLNode = xmlNodePtr
  66. //
  67. // So, for example:
  68. // + (id)nodeConsumingXMLNode:(xmlNodePtr)theXMLNode;
  69. @class NSArray, NSDictionary, NSError, NSString, NSURL;
  70. @class GDataXMLElement, GDataXMLDocument;
  71. enum {
  72. GDataXMLInvalidKind = 0,
  73. GDataXMLDocumentKind,
  74. GDataXMLElementKind,
  75. GDataXMLAttributeKind,
  76. GDataXMLNamespaceKind,
  77. GDataXMLProcessingInstructionKind,
  78. GDataXMLCommentKind,
  79. GDataXMLTextKind,
  80. GDataXMLDTDKind,
  81. GDataXMLEntityDeclarationKind,
  82. GDataXMLAttributeDeclarationKind,
  83. GDataXMLElementDeclarationKind,
  84. GDataXMLNotationDeclarationKind
  85. };
  86. typedef NSUInteger GDataXMLNodeKind;
  87. @interface GDataXMLNode : NSObject <NSCopying> {
  88. @protected
  89. // NSXMLNodes can have a namespace URI or prefix even if not part
  90. // of a tree; xmlNodes cannot. When we create nodes apart from
  91. // a tree, we'll store the dangling prefix or URI in the xmlNode's name,
  92. // like
  93. // "prefix:name"
  94. // or
  95. // "{http://uri}:name"
  96. //
  97. // We will fix up the node's namespace and name (and those of any children)
  98. // later when adding the node to a tree with addChild: or addAttribute:.
  99. // See fixUpNamespacesForNode:.
  100. xmlNodePtr xmlNode_; // may also be an xmlAttrPtr or xmlNsPtr
  101. BOOL shouldFreeXMLNode_; // if yes, xmlNode_ will be free'd in dealloc
  102. // cached values
  103. NSString *cachedName_;
  104. NSArray *cachedChildren_;
  105. NSArray *cachedAttributes_;
  106. }
  107. + (GDataXMLElement *)elementWithName:(NSString *)name;
  108. + (GDataXMLElement *)elementWithName:(NSString *)name stringValue:(NSString *)value;
  109. + (GDataXMLElement *)elementWithName:(NSString *)name URI:(NSString *)value;
  110. + (id)attributeWithName:(NSString *)name stringValue:(NSString *)value;
  111. + (id)attributeWithName:(NSString *)name URI:(NSString *)attributeURI stringValue:(NSString *)value;
  112. + (id)namespaceWithName:(NSString *)name stringValue:(NSString *)value;
  113. + (id)textWithStringValue:(NSString *)value;
  114. - (NSString *)stringValue;
  115. - (void)setStringValue:(NSString *)str;
  116. - (NSUInteger)childCount;
  117. - (NSArray *)children;
  118. - (GDataXMLNode *)childAtIndex:(unsigned)index;
  119. - (NSString *)localName;
  120. - (NSString *)name;
  121. - (NSString *)prefix;
  122. - (NSString *)URI;
  123. - (GDataXMLNodeKind)kind;
  124. - (NSString *)XMLString;
  125. + (NSString *)localNameForName:(NSString *)name;
  126. + (NSString *)prefixForName:(NSString *)name;
  127. // This is the preferred entry point for nodesForXPath. This takes an explicit
  128. // namespace dictionary (keys are prefixes, values are URIs).
  129. - (NSArray *)nodesForXPath:(NSString *)xpath namespaces:(NSDictionary *)namespaces error:(NSError **)error;
  130. - (GDataXMLNode *)firstNodeForXPath:(NSString *)xpath namespaces:(NSDictionary *)namespaces error:(NSError **)error;
  131. // This implementation of nodesForXPath registers namespaces only from the
  132. // document's root node. _def_ns may be used as a prefix for the default
  133. // namespace, though there's no guarantee that the default namespace will
  134. // be consistenly the same namespace in server responses.
  135. - (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error;
  136. - (GDataXMLNode *)firstNodeForXPath:(NSString *)xpath error:(NSError **)error;
  137. // access to the underlying libxml node; be sure to release the cached values
  138. // if you change the underlying tree at all
  139. - (xmlNodePtr)XMLNode;
  140. - (void)releaseCachedValues;
  141. @end
  142. @interface GDataXMLElement : GDataXMLNode
  143. - (id)initWithXMLString:(NSString *)str error:(NSError **)error;
  144. - (id)initWithHTMLString:(NSString *)str error:(NSError **)error;
  145. - (NSArray *)namespaces;
  146. - (void)setNamespaces:(NSArray *)namespaces;
  147. - (void)addNamespace:(GDataXMLNode *)aNamespace;
  148. // addChild adds a copy of the child node to the element
  149. - (void)addChild:(GDataXMLNode *)child;
  150. - (void)removeChild:(GDataXMLNode *)child;
  151. - (NSArray *)elementsForName:(NSString *)name;
  152. - (NSArray *)elementsForLocalName:(NSString *)localName URI:(NSString *)URI;
  153. - (NSArray *)attributes;
  154. - (GDataXMLNode *)attributeForName:(NSString *)name;
  155. - (GDataXMLNode *)attributeForLocalName:(NSString *)name URI:(NSString *)attributeURI;
  156. - (void)addAttribute:(GDataXMLNode *)attribute;
  157. - (NSString *)resolvePrefixForNamespaceURI:(NSString *)namespaceURI;
  158. @end
  159. @interface GDataXMLDocument : NSObject {
  160. @protected
  161. xmlDoc* xmlDoc_; // strong; always free'd in dealloc
  162. NSStringEncoding _encoding;
  163. }
  164. - (id)initWithXMLString:(NSString *)str encoding:(NSStringEncoding)encoding error:(NSError **)error;
  165. - (id)initWithData:(NSData *)data encoding:(NSStringEncoding)encoding error:(NSError **)error;
  166. - (id)initWithHTMLString:(NSString *)str encoding:(NSStringEncoding)encoding error:(NSError **)error;
  167. - (id)initWithHTMLData:(NSData *)data encoding:(NSStringEncoding)encoding error:(NSError **)error;
  168. - (id)initWithXMLString:(NSString *)str error:(NSError **)error;
  169. - (id)initWithData:(NSData *)data error:(NSError **)error;
  170. - (id)initWithHTMLString:(NSString *)str error:(NSError **)error;
  171. - (id)initWithHTMLData:(NSData *)data error:(NSError **)error;
  172. // initWithRootElement uses a copy of the argument as the new document's root
  173. - (id)initWithRootElement:(GDataXMLElement *)element;
  174. - (GDataXMLElement *)rootElement;
  175. - (NSData *)XMLData;
  176. - (void)setVersion:(NSString *)version;
  177. - (void)setCharacterEncoding:(NSString *)encoding;
  178. // This is the preferred entry point for nodesForXPath. This takes an explicit
  179. // namespace dictionary (keys are prefixes, values are URIs).
  180. - (NSArray *)nodesForXPath:(NSString *)xpath namespaces:(NSDictionary *)namespaces error:(NSError **)error;
  181. // Convenience method returns first element with speciifed xpath or nil
  182. - (GDataXMLNode *)firstNodeForXPath:(NSString *)xpath namespaces:(NSDictionary *)namespaces error:(NSError **)error;
  183. // This implementation of nodesForXPath registers namespaces only from the
  184. // document's root node. _def_ns may be used as a prefix for the default
  185. // namespace, though there's no guarantee that the default namespace will
  186. // be consistenly the same namespace in server responses.
  187. - (NSArray *)nodesForXPath:(NSString *)xpath error:(NSError **)error;
  188. - (GDataXMLNode *)firstNodeForXPath:(NSString *)xpath error:(NSError **)error;
  189. - (NSString *)description;
  190. @end