]> mj.ucw.cz Git - libucw.git/blobdiff - ucw-xml/xml.h
JSON: Remove unused includes
[libucw.git] / ucw-xml / xml.h
index c048f56cab8a44acb09a0c43af03a2d542f5184a..1712607367d70403adcedb9c9f3a06c05ad4f1c7 100644 (file)
@@ -2,6 +2,7 @@
  *     UCW Library -- A simple XML parser
  *
  *     (c) 2007--2008 Pavel Charvat <pchar@ucw.cz>
+ *     (c) 2015 Martin Mares <mj@ucw.cz>
  *
  *     This software may be freely distributed and used according to the terms
  *     of the GNU Lesser General Public License.
 
 #ifdef CONFIG_UCW_CLEAN_ABI
 #define xml_attr_find ucw_xml_attr_find
+#define xml_attr_find_ns ucw_xml_attr_find_ns
+#define xml_attr_qname ucw_xml_attr_qname
 #define xml_attr_value ucw_xml_attr_value
+#define xml_attr_value_ns ucw_xml_attr_value_ns
 #define xml_cleanup ucw_xml_cleanup
 #define xml_def_find_entity ucw_xml_def_find_entity
 #define xml_def_resolve_entity ucw_xml_def_resolve_entity
 #define xml_merge_dom_chars ucw_xml_merge_dom_chars
 #define xml_next ucw_xml_next
 #define xml_next_state ucw_xml_next_state
+#define xml_node_qname ucw_xml_node_qname
 #define xml_normalize_white ucw_xml_normalize_white
+#define xml_ns_by_id ucw_xml_ns_by_id
+#define xml_ns_by_name ucw_xml_ns_by_name
+#define xml_ns_enable ucw_xml_ns_enable
 #define xml_parse ucw_xml_parse
 #define xml_push_fastbuf ucw_xml_push_fastbuf
 #define xml_reset ucw_xml_reset
 #define xml_warn ucw_xml_warn
 #endif
 
+/***
+ * === Constants
+ ***/
+
 struct xml_context;
 struct xml_dtd_entity;
 
+/** Error code reported by the parser. So far, only the basic error classes are recognized. **/
 enum xml_error {
   XML_ERR_OK = 0,
   XML_ERR_WARN = 1000,                                 /* Warning */
@@ -48,6 +61,7 @@ enum xml_error {
   XML_ERR_EOF,
 };
 
+/** Parser state. A pull parser returns one of these to indicate the type of the current node. **/
 enum xml_state {
   XML_STATE_EOF,                                       /* EOF or a fatal error */
   XML_STATE_START,                                     /* Initial state */
@@ -71,6 +85,7 @@ enum xml_state {
   XML_STATE_EPILOG_PI,
 };
 
+/** Pull requests: a bit mask of node types you want to return. The other nodes are silently skipped. **/
 enum xml_pull {
   XML_PULL_XML_DECL =                  0x00000001,     /* Stop after the XML declaration */
   XML_PULL_DOCTYPE_DECL =              0x00000002,     /* Stop in the doctype declaration (before optional internal subset) */
@@ -82,6 +97,7 @@ enum xml_pull {
   XML_PULL_ALL =                       0xffffffff,
 };
 
+/** Parser mode flags. **/
 enum xml_flags {
   /* Enable reporting of various events via SAX and/or PULL interface */
   XML_REPORT_COMMENTS =                        0x00000001,     /* Report comments */
@@ -104,6 +120,7 @@ enum xml_flags {
   XML_PARSE_DTD =                      0x00000200,     /* Enable parsing of DTD */
   XML_NO_CHARS =                       0x00000400,     /* The current element must not contain character data (filled automaticaly if using DTD) */
   XML_ALLOC_DEFAULT_ATTRS =            0x00000800,     /* Allocate default attribute values so they can be found by XML_ATTR_FOR_EACH */
+  XML_NAMESPACES =                     0x00001000,     /* Parse namespaces, use xml_ns_enable() to set this */
 
   /* Internals, do not change! */
   XML_EMPTY_ELEM_TAG =                 0x00010000,     /* The current element match EmptyElemTag */
@@ -117,20 +134,41 @@ enum xml_flags {
   XML_SRC_EXTERNAL =                   0x00800000,     /* An external entity */
 };
 
+/***
+ * === Internal representation of DOM
+ *
+ * All DOM nodes are allocated within temporary memory pools and they are not
+ * guaranteed to survive when the parser leaves the element. Upon <<xml_cleanup()>>,
+ * all remaining nodes are always freed.
+ ***/
+
+/** Node types **/
 enum xml_node_type {
-  XML_NODE_ELEM,
-  XML_NODE_COMMENT,
-  XML_NODE_CHARS,
-  XML_NODE_PI,
+  XML_NODE_ELEM,                       /* Element */
+  XML_NODE_COMMENT,                    /* Comment */
+  XML_NODE_CHARS,                      /* Character data */
+  XML_NODE_PI,                         /* Processing instruction */
 };
 
+/** Iterate over all children of a node. **/
 #define XML_NODE_FOR_EACH(var, node) CLIST_FOR_EACH(struct xml_node *, var, (node)->sons)
+
+/** Iterate over all attributes of a node. **/
 #define XML_ATTR_FOR_EACH(var, node) SLIST_FOR_EACH(struct xml_attr *, var, (node)->attrs)
 
+/** A single DOM node. **/
 struct xml_node {
   cnode n;                                             /* Node for list of parent's sons */
   uint type;                                           /* XML_NODE_x */
   struct xml_node *parent;                             /* Parent node */
+  /*
+   *  If namespaces are enabled, node->name points to the local part of the name
+   *  and node->ns is the resolved namespace ID.
+   *
+   *  However, the namespace prefix is kept in memory just before the local part,
+   *  so you can use xml_node_qname() to find out the full qualified name.
+   *  The same applies to attributes, but the function is xml_attr_qname().
+   */
   char *name;                                          /* Element name / PI target */
   clist sons;                                          /* Children nodes */
   union {
@@ -139,6 +177,7 @@ struct xml_node {
       uint len;                                                /* Text length in bytes */
     };
     struct {
+      uint ns;                                         /* Namespace ID */
       struct xml_dtd_elem *dtd;                                /* Element DTD */
       slist attrs;                                     /* Link list of element attributes */
     };
@@ -146,11 +185,14 @@ struct xml_node {
   void *user;                                          /* User-defined (initialized to NULL) */
 };
 
+/** A single attribute. **/
 struct xml_attr {
   snode n;                                             /* Node for elem->attrs */
+  uint hash;                                           /* Internal hash of ns + name */
   struct xml_node *elem;                               /* Parent element */
   struct xml_dtd_attr *dtd;                            /* Attribute DTD */
-  char *name;                                          /* Attribute name */
+  uint ns;                                             /* Namespace ID */
+  char *name;                                          /* Attribute name without NS prefix */
   char *val;                                           /* Attribute value */
   void *user;                                          /* User-defined (initialized to NULL) */
 };
@@ -177,6 +219,42 @@ struct xml_source {
   uint pending_0xd;                                    /* The last read character is 0xD */
 };
 
+/** Finds a qualified name (including namespace prefix) of a given element node. **/
+char *xml_node_qname(struct xml_context *ctx, struct xml_node *node);
+
+/** Finds a qualified name (including namespace prefix) of a given attribute. **/
+char *xml_attr_qname(struct xml_context *ctx, struct xml_attr *node);
+
+/** Finds a given attribute value in a `XML_NODE_ELEM` node **/
+struct xml_attr *xml_attr_find(struct xml_context *ctx, struct xml_node *node, char *name);
+
+/** The same, but namespace-aware **/
+struct xml_attr *xml_attr_find_ns(struct xml_context *ctx, struct xml_node *node, uint ns, char *name);
+
+/** Similar to xml_attr_find, but it deals also with default values **/
+char *xml_attr_value(struct xml_context *ctx, struct xml_node *node, char *name);
+
+/** The same, but namespace-aware **/
+char *xml_attr_value_ns(struct xml_context *ctx, struct xml_node *node, uint ns, char *name);
+
+/** Remove leading/trailing spaces and replaces sequences of spaces to a single space character (non-CDATA attribute normalization) **/
+uint xml_normalize_white(struct xml_context *ctx, char *value);
+
+/** Merge character contents of a given element to a single string (not recursive) **/
+char *xml_merge_chars(struct xml_context *ctx, struct xml_node *node, struct mempool *pool);
+
+/** Merge character contents of a given subtree to a single string **/
+char *xml_merge_dom_chars(struct xml_context *ctx, struct xml_node *node, struct mempool *pool);
+
+/***
+ * === Parser context
+ ***/
+
+/**
+ * The state of the parser is kept in this structure. There are some
+ * user-accessible parts (like pointers to various hooks), but the
+ * majority of fields is private.
+ **/
 struct xml_context {
   /* Error handling */
   char *err_msg;                                       /* Last error message */
@@ -186,7 +264,7 @@ struct xml_context {
   void (*h_error)(struct xml_context *ctx);            /* Recoverable error callback */
   void (*h_fatal)(struct xml_context *ctx);            /* Unrecoverable error callback */
 
-  /* Memory management */
+  /* Memory management (private) */
   struct mempool *pool;                                        /* DOM pool */
   struct mempool *stack;                               /* Stack pool (freed as soon as possible) */
   struct xml_stack *stack_list;                                /* See xml_push(), xml_pop() */
@@ -195,9 +273,8 @@ struct xml_context {
   struct fastbuf chars;                                        /* Character data / attribute value */
   struct mempool_state chars_state;                    /* Mempool state before the current character block has started */
   char *chars_trivial;                                 /* If not empty, it will be appended to chars */
-  void *tab_attrs;                                     /* Hash table of element attributes */
 
-  /* Input */
+  /* Input (private) */
   struct xml_source *src;                              /* Current source */
   u32 *bptr, *bstop;                                   /* Buffer with preprocessed characters (validated UCS-4 + category flags) */
   uint cat_chars;                                      /* Unicode range of supported characters (cdata, attribute values, ...) */
@@ -228,6 +305,15 @@ struct xml_context {
   struct xml_node *dom;                                        /* DOM root */
   struct xml_node *node;                               /* Current DOM node */
 
+  /* Namespaces (private) */
+  struct mempool *ns_pool;                             /* Memory pool for NS definitions */
+  const char **ns_by_id;                               /* A growing array translating NS IDs to their names */
+  void *ns_by_name;                                    /* Hash table translating NS names to their IDs */
+  void *ns_by_prefix;                                  /* Hash table translating current prefixes to NS IDs, allocated from xml->stack */
+  struct xml_ns_prefix *ns_prefix_stack;               /* A stack of prefix definitions, allocated from xml->stack */
+  uint ns_default;                                     /* Current default namespace */
+
+  /* Other stuff */
   char *version_str;
   uint standalone;
   char *doctype;                                       /* The document type (or NULL if unknown) */
@@ -238,57 +324,81 @@ struct xml_context {
   uint pull;                                           /* Parameters for the PULL interface (XML_PULL_x) */
 };
 
-/* Initialize XML context */
+/** Initialize XML context **/
 void xml_init(struct xml_context *ctx);
 
-/* Clean up all internal structures */
+/** Clean up all internal structures **/
 void xml_cleanup(struct xml_context *ctx);
 
-/* Reuse XML context, equivalent to xml_cleanup() and xml_init() */
+/** Reuse XML context, equivalent to xml_cleanup() and xml_init(), but faster **/
 void xml_reset(struct xml_context *ctx);
 
-/* Add XML source (fastbuf will be automatically closed) */
+/** Add XML source (fastbuf will be automatically closed) **/
 struct xml_source *xml_push_fastbuf(struct xml_context *ctx, struct fastbuf *fb);
 
-/* Parse without the PULL interface, return XML_ERR_x code (zero on success) */
+/** Parse the whole document without the PULL interface, return `XML_ERR_x` code (zero on success) **/
 uint xml_parse(struct xml_context *ctx);
 
-/* Parse with the PULL interface, return XML_STATE_x (zero on EOF or fatal error) */
+/** Parse with the PULL interface, return `XML_STATE_x` (zero on EOF or fatal error) **/
 uint xml_next(struct xml_context *ctx);
 
-/* Equivalent to xml_next, but with temporarily changed ctx->pull value */
+/** Equivalent to xml_next, but with temporarily changed ctx->pull value **/
 uint xml_next_state(struct xml_context *ctx, uint pull);
 
-/* May be called on XML_STATE_STAG to skip it's content; can return XML_STATE_ETAG or XML_STATE_EOF on fatal error */
+/** May be called on XML_STATE_STAG to skip its content; can return `XML_STATE_ETAG` or `XML_STATE_EOF` on fatal error **/
 uint xml_skip_element(struct xml_context *ctx);
 
-/* Returns the current row number in the document entity */
+/** Returns the current row (line) number in the document entity **/
 uint xml_row(struct xml_context *ctx);
 
-/* Finds a given attribute value in a XML_NODE_ELEM node */
-struct xml_attr *xml_attr_find(struct xml_context *ctx, struct xml_node *node, char *name);
-
-/* Similar to xml_attr_find, but it deals also with default values */
-char *xml_attr_value(struct xml_context *ctx, struct xml_node *node, char *name);
-
 /* The default value of h_find_entity(), knows &lt;, &gt;, &amp;, &apos; and &quot; */
 struct xml_dtd_entity *xml_def_find_entity(struct xml_context *ctx, char *name);
 
 /* The default value of h_resolve_entity(), throws an error */
 void xml_def_resolve_entity(struct xml_context *ctx, struct xml_dtd_entity *ent);
 
-/* Remove leading/trailing spaces and replaces sequences of spaces to a single space character (non-CDATA attribute normalization) */
-uint xml_normalize_white(struct xml_context *ctx, char *value);
-
-/* Merge character contents of a given element to a single string (not recursive) */
-char *xml_merge_chars(struct xml_context *ctx, struct xml_node *node, struct mempool *pool);
-
-/* Merge character contents of a given subtree to a single string */
-char *xml_merge_dom_chars(struct xml_context *ctx, struct xml_node *node, struct mempool *pool);
-
-/* Public part of error handling */
+/** Throw a warning at the current node **/
 void xml_warn(struct xml_context *ctx, const char *format, ...);
+
+/** Throw an error at the current node **/
 void xml_error(struct xml_context *ctx, const char *format, ...);
+
+/** Throw a fatal error, aborting parsing. This can be called only from SAX hooks (and from parser internals). **/
 void NONRET xml_fatal(struct xml_context *ctx, const char *format, ...);
 
+/***
+ * === Namespaces
+ *
+ * When namespace-aware parsing is requested by calling xml_ns_enable(),
+ * all namespaces are collected and assigned integer identifiers. Names of
+ * elements and attributes then always contain a namespace ID and a local
+ * name within the namespace. An ID of zero corresponds to an unspecified
+ * namespace.
+ *
+ * Once an ID is assigned, it is never changed, even if the namespace
+ * goes out of scope temporarily.
+ */
+
+/** Request processing of namespaces (must be called before the first node is parsed). **/
+void xml_ns_enable(struct xml_context *ctx);
+
+/**
+ * Looks up namespace by its ID, dies on an invalid ID. Returns a pointer
+ * which remains valid until the context is cleaned up or reset.
+ **/
+const char *xml_ns_by_id(struct xml_context *ctx, uint ns);
+
+/**
+ * Looks up namespace by its name and returns its ID. Assigns a new ID if necessary.
+ * When this function returns, @name is not referenced any more.
+ **/
+uint xml_ns_by_name(struct xml_context *ctx, const char *name);
+
+/** Well-known namespaces. **/
+enum xml_ns_id {
+  XML_NS_NONE = 0,             /* This element has no namespace */
+  XML_NS_XMLNS = 1,            /* xmlns: */
+  XML_NS_XML = 2,              /* xml: */
+};
+
 #endif