| /******************************************************************************* |
| * Copyright (C) 2004-2006 Intel Corp. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * - Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * - Neither the name of Intel Corp. nor the names of its |
| * contributors may be used to endorse or promote products derived from this |
| * software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| * ARE DISCLAIMED. IN NO EVENT SHALL Intel Corp. OR THE CONTRIBUTORS |
| * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGE. |
| *******************************************************************************/ |
| |
| /** |
| * @author Anas Nashif |
| */ |
| #ifdef HAVE_CONFIG_H |
| #include <wsman_config.h> |
| #endif |
| |
| #include <string.h> |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <ctype.h> |
| |
| #include <assert.h> |
| |
| #include <libxml/xmlmemory.h> |
| #include <libxml/parser.h> |
| #include <libxml/xmlstring.h> |
| |
| #include <libxml/xpath.h> |
| #include <libxml/xpathInternals.h> |
| |
| |
| #include "u/libu.h" |
| #include "wsman-xml-api.h" |
| #include "wsman-soap.h" |
| #include "wsman-xml.h" |
| #include "wsman-xml-binding.h" |
| |
| |
| static void destroy_attr_private_data(void *data) |
| { |
| if (data) |
| xmlFree(data); |
| } |
| |
| |
| static void destroy_node_private_data(void *_data) |
| { |
| iWsNode *data = (iWsNode *) _data; |
| if (data) { |
| // ??? TBD data->nsQNameList; |
| if (data->valText) |
| xmlFree(data->valText); |
| u_free(data); |
| } |
| } |
| |
| static void destroy_tree_private_data(xmlNode * node) |
| { |
| while (node) { |
| xmlAttrPtr attr = node->properties; |
| |
| if (node->_private) { |
| destroy_node_private_data(node->_private); |
| node->_private = NULL; |
| } |
| |
| while (attr) { |
| if (attr->_private) { |
| destroy_attr_private_data(attr->_private); |
| attr->_private = NULL; |
| } |
| attr = attr->next; |
| } |
| destroy_tree_private_data(node->children); |
| node = node->next; |
| } |
| } |
| |
| static void |
| myXmlErrorReporting (void *ctx, const char* msg, ...) |
| { |
| va_list args; |
| char *string; |
| va_start(args, msg); |
| string = u_strdup_vprintf (msg, args); |
| warning (string); |
| va_end(args); |
| |
| u_free(string); |
| } |
| |
| void xml_parser_initialize() |
| { |
| xmlSetGenericErrorFunc(NULL, myXmlErrorReporting); |
| } |
| |
| void xml_parser_destroy() |
| { |
| } |
| |
| int xml_parser_utf8_strlen(char *buf) |
| { |
| return xmlUTF8Strlen(BAD_CAST buf); |
| } |
| |
| void xml_parser_doc_to_memory(WsXmlDocH doc, char **buf, |
| int *ptrSize, const char *encoding) |
| { |
| if (doc && buf && ptrSize) |
| xmlDocDumpMemoryEnc(doc->parserDoc, |
| (xmlChar **) buf, ptrSize, |
| (!encoding) ? "UTF-8" : encoding); |
| } |
| |
| void xml_parser_free_memory(void *ptr) |
| { |
| if (ptr) |
| xmlFree(ptr); |
| } |
| |
| |
| |
| int xml_parser_create_doc_by_import(WsXmlDocH wsDoc, WsXmlNodeH node) |
| { |
| xmlDocPtr doc; |
| xmlNodePtr rootNode; |
| |
| if ((doc = xmlNewDoc(BAD_CAST "1.0")) == NULL) { |
| if (doc) |
| xmlFreeDoc(doc); |
| return 0; |
| } else { |
| doc->_private = wsDoc; |
| wsDoc->parserDoc = doc; |
| rootNode = xmlDocCopyNode((xmlNodePtr) node, doc, 1); |
| xmlDocSetRootElement(doc, rootNode); |
| return 1; |
| } |
| } |
| |
| int xml_parser_create_doc(WsXmlDocH wsDoc, const char *rootName) |
| { |
| int retVal = 0; |
| xmlDocPtr doc; |
| xmlNodePtr rootNode; |
| |
| if ((doc = xmlNewDoc(BAD_CAST "1.0")) == NULL || |
| (rootNode = xmlNewNode(NULL, BAD_CAST rootName)) == NULL) { |
| if (doc) |
| xmlFreeDoc(doc); |
| } else { |
| doc->_private = wsDoc; |
| wsDoc->parserDoc = doc; |
| xmlDocSetRootElement(doc, rootNode); |
| retVal = 1; |
| } |
| |
| return retVal; |
| } |
| |
| |
| |
| void xml_parser_destroy_doc(WsXmlDocH wsDoc) |
| { |
| xmlDocPtr xmlDoc = (xmlDocPtr) wsDoc->parserDoc; |
| if (xmlDoc != NULL) { |
| destroy_tree_private_data(xmlDocGetRootElement(xmlDoc)); |
| xmlFreeDoc(xmlDoc); |
| } |
| } |
| |
| |
| WsXmlDocH xml_parser_get_doc(WsXmlNodeH node) |
| { |
| xmlDocPtr xmlDoc = ((xmlDocPtr) node)->doc; |
| return (WsXmlDocH) (!xmlDoc ? NULL : xmlDoc->_private); |
| } |
| |
| |
| WsXmlNodeH xml_parser_get_root(WsXmlDocH doc) |
| { |
| if (doc->parserDoc != NULL) |
| return (WsXmlNodeH) xmlDocGetRootElement((xmlDocPtr) doc-> |
| parserDoc); |
| return NULL; |
| } |
| |
| WsXmlDocH |
| xml_parser_file_to_doc( const char *filename, |
| const char *encoding, unsigned long options) |
| { |
| xmlDocPtr xmlDoc; |
| WsXmlDocH Doc = NULL; |
| |
| xmlDoc = xmlReadFile(filename, encoding, |
| XML_PARSE_NONET | XML_PARSE_NSCLEAN); |
| if (xmlDoc == NULL) { |
| return NULL; |
| } |
| Doc = (WsXmlDocH) u_zalloc(sizeof(*Doc)); |
| if (Doc == NULL) { |
| xmlFreeDoc(xmlDoc); |
| return NULL; |
| } |
| xmlDoc->_private = Doc; |
| Doc->parserDoc = xmlDoc; |
| |
| return Doc; |
| |
| } |
| |
| WsXmlDocH |
| xml_parser_memory_to_doc( const char *buf, size_t size, |
| const char *encoding, unsigned long options) |
| { |
| WsXmlDocH Doc = NULL; |
| xmlDocPtr xmlDoc; |
| if (!buf || !size ) { |
| return NULL; |
| } |
| xmlDoc = xmlReadMemory(buf, (int) size, NULL, encoding, |
| XML_PARSE_NONET | XML_PARSE_NSCLEAN); |
| if (xmlDoc == NULL) { |
| return NULL; |
| } |
| Doc = (WsXmlDocH) u_zalloc(sizeof(*Doc)); |
| if (Doc == NULL) { |
| xmlFreeDoc(xmlDoc); |
| return NULL; |
| } |
| |
| xmlDoc->_private = Doc; |
| Doc->parserDoc = xmlDoc; |
| |
| return Doc; |
| } |
| |
| |
| char *xml_parser_node_query(WsXmlNodeH node, int what) |
| { |
| char *ptr = NULL; |
| xmlNodePtr xmlNode = (xmlNodePtr) node; |
| iWsNode *wsNode = (iWsNode *) xmlNode->_private; |
| |
| switch (what) { |
| case XML_TEXT_VALUE: |
| if (wsNode == NULL) |
| xmlNode->_private = wsNode = |
| u_zalloc(sizeof(iWsNode)); |
| |
| if (wsNode != NULL) { |
| if (wsNode->valText == NULL) { |
| wsNode->valText = |
| (char *) xmlNodeGetContent(xmlNode); |
| } |
| ptr = wsNode->valText; |
| } |
| break; |
| case XML_LOCAL_NAME: |
| ptr = (char *) xmlNode->name; |
| break; |
| case XML_NS_URI: |
| if (xmlNode->ns != NULL) |
| ptr = (char *) xmlNode->ns->href; |
| break; |
| case XML_NS_PREFIX: |
| if (xmlNode->ns != NULL) |
| ptr = (char *) xmlNode->ns->prefix; |
| break; |
| default: |
| break; |
| } |
| |
| return ptr; |
| } |
| |
| |
| int xml_parser_node_set(WsXmlNodeH node, int what, const char *str) |
| { |
| int retVal = -1; |
| xmlNodePtr xmlNode = (xmlNodePtr) node; |
| iWsNode *wsNode = (iWsNode *) xmlNode->_private; |
| xmlNsPtr xmlNs; |
| |
| switch (what) { |
| case XML_TEXT_VALUE: |
| if (wsNode == NULL) |
| xmlNode->_private = wsNode = |
| u_zalloc(sizeof(iWsNode)); |
| |
| if (wsNode != NULL) { |
| if (wsNode->valText != NULL) { |
| xmlFree(wsNode->valText); |
| wsNode->valText = NULL; |
| } |
| xmlNodeSetContent(xmlNode, BAD_CAST str); |
| retVal = 0; |
| } |
| break; |
| |
| case XML_LOCAL_NAME: |
| xmlNodeSetName(xmlNode, BAD_CAST str); |
| retVal = 0; |
| break; |
| |
| case XML_NS_URI: |
| if ((xmlNs = |
| (xmlNsPtr) xml_parser_ns_find(node, str, NULL, 1, |
| 1)) != NULL) { |
| xmlNode->ns = xmlNs; |
| retVal = 0; |
| } else |
| retVal = 1; |
| break; |
| default: |
| retVal = 1; |
| break; |
| } |
| |
| return retVal; |
| } |
| |
| |
| |
| WsXmlNodeH xml_parser_node_get(WsXmlNodeH node, int which) |
| { |
| xmlNodePtr xmlNode = NULL; |
| xmlNodePtr base = (xmlNodePtr) node; |
| |
| switch (which) { |
| case XML_ELEMENT_PARENT: |
| xmlNode = base->parent; |
| break; |
| case XML_ELEMENT_NEXT: |
| if ((xmlNode = base->next) != NULL) { |
| do { |
| if (xmlNode->type == XML_ELEMENT_NODE) |
| break; |
| } |
| while ((xmlNode = xmlNode->next) != NULL); |
| } |
| break; |
| case XML_ELEMENT_PREV: |
| if ((xmlNode = base->prev) != NULL) { |
| do { |
| if (xmlNode->type == XML_ELEMENT_NODE) |
| break; |
| } |
| while ((xmlNode = xmlNode->prev) != NULL); |
| } |
| break; |
| case XML_LAST_CHILD: |
| default: |
| if (which >= 0 || which == XML_LAST_CHILD) { |
| int count = 0; |
| xmlNode = base->children; |
| |
| while (xmlNode) { |
| if (xmlNode->type == XML_ELEMENT_NODE) { |
| if (which == XML_LAST_CHILD && |
| xmlNode->next == NULL) |
| break; |
| |
| if (count == which) |
| break; |
| |
| count++; |
| } |
| xmlNode = xmlNode->next; |
| } |
| } else { |
| assert(which >= 0); |
| } |
| break; |
| } |
| return (WsXmlNodeH) xmlNode; |
| } |
| |
| |
| WsXmlNsH |
| xml_parser_ns_find(WsXmlNodeH node, |
| const char *uri, |
| const char *prefix, |
| int bWalkUpTree, int bAddAtRootIfNotFound) |
| { |
| xmlNodePtr xmlNode = (xmlNodePtr) node; |
| xmlNsPtr xmlNs = NULL; |
| |
| while (xmlNode != NULL) { |
| xmlNs = xmlNode->nsDef; |
| while (xmlNs != NULL) { |
| if (uri) { |
| if (!strcmp((char *) xmlNs->href, uri)) |
| break; |
| } else if (prefix == NULL) { |
| if (xmlNs->prefix == NULL) |
| break; |
| } else |
| if (xmlNs->prefix && |
| !strcmp((char *) xmlNs->prefix, prefix)) { |
| break; |
| } |
| xmlNs = xmlNs->next; |
| } |
| if (xmlNs != NULL || !bWalkUpTree) |
| break; |
| xmlNode = xmlNode->parent; |
| } |
| |
| if (xmlNs == NULL && bAddAtRootIfNotFound) { |
| xmlNodePtr xmlRoot = |
| xmlDocGetRootElement(((xmlDocPtr) node)->doc); |
| char buf[12]; |
| |
| if (prefix == NULL) { |
| ws_xml_make_default_prefix((WsXmlNodeH) xmlRoot, |
| uri, buf, sizeof(buf)); |
| prefix = buf; |
| } |
| xmlNs = |
| (xmlNsPtr) xml_parser_ns_add((WsXmlNodeH) xmlRoot, uri, |
| prefix); |
| } |
| return (WsXmlNsH) xmlNs; |
| } |
| |
| char *xml_parser_ns_query(WsXmlNsH ns, int what) |
| { |
| xmlNsPtr xmlNs = (xmlNsPtr) ns; |
| char *ptr = NULL; |
| |
| switch (what) { |
| case XML_NS_URI: |
| ptr = (char *) xmlNs->href; |
| break; |
| case XML_NS_PREFIX: |
| ptr = (char *) xmlNs->prefix; |
| break; |
| default: |
| assert(what == XML_NS_URI); |
| break; |
| } |
| return ptr; |
| } |
| |
| |
| WsXmlNsH |
| xml_parser_ns_add(WsXmlNodeH node, const char *uri, const char *prefix) |
| { |
| xmlNsPtr xmlNs = NULL; |
| if (node && uri) { |
| if ((xmlNs = |
| (xmlNsPtr) xml_parser_ns_find(node, uri, NULL, 0, |
| 0)) != NULL) { |
| if (xmlNs->prefix != NULL) { |
| xmlFree((char *) xmlNs->prefix); |
| xmlNs->prefix = NULL; |
| } |
| |
| if (prefix != NULL) { |
| xmlNs->prefix = xmlStrdup(BAD_CAST prefix); |
| } |
| } else { |
| xmlNs = |
| xmlNewNs((xmlNodePtr) node, BAD_CAST uri, |
| BAD_CAST prefix); |
| } |
| } |
| return (WsXmlNsH) xmlNs; |
| } |
| |
| |
| int xml_parser_ns_remove(WsXmlNodeH node, const char *nsUri) |
| { |
| int retVal = -1; |
| |
| if (node && nsUri) { |
| xmlNodePtr xmlNode = (xmlNodePtr) node; |
| xmlNsPtr xmlNs = xmlNode->nsDef; |
| xmlNsPtr prevNs = NULL; |
| |
| while (xmlNs != NULL) { |
| if ((xmlStrEqual(xmlNs->href, BAD_CAST nsUri))) { |
| break; |
| } |
| prevNs = xmlNs; |
| xmlNs = xmlNs->next; |
| } |
| |
| if (xmlNs != NULL) { |
| retVal = 0; |
| if (prevNs == NULL) |
| xmlNode->nsDef = xmlNs->next; |
| else |
| prevNs->next = xmlNs->next; |
| xmlFreeNs(xmlNs); |
| } else |
| retVal = 1; |
| } |
| return retVal; |
| } |
| |
| |
| |
| WsXmlNsH xml_parser_ns_get(WsXmlNodeH node, int which) |
| { |
| xmlNodePtr xmlNode = (xmlNodePtr) node; |
| xmlNsPtr xmlNs = NULL; |
| |
| if (which >= 0) { |
| int count = 0; |
| xmlNs = xmlNode->nsDef; |
| while (xmlNs != NULL) { |
| if (which == count) |
| break; |
| count++; |
| xmlNs = xmlNs->next; |
| } |
| } else { |
| assert(which >= 0); |
| } |
| return (WsXmlNsH) xmlNs; |
| } |
| |
| |
| static |
| int get_ns_count_at_node(xmlNodePtr xmlNode) |
| { |
| int count = 0; |
| xmlNsPtr xmlNs = xmlNode->nsDef; |
| |
| while (xmlNs != NULL) { |
| count++; |
| xmlNs = xmlNs->next; |
| } |
| return count; |
| } |
| |
| |
| int xml_parser_get_count(WsXmlNodeH node, int what, int bWalkUpTree) |
| { |
| int count = 0; |
| xmlNodePtr xmlNode; |
| xmlAttrPtr xmlAttr; |
| |
| switch (what) { |
| case XML_COUNT_NODE: |
| xmlNode = ((xmlNodePtr) node)->children; |
| while (xmlNode) { |
| if (xmlNode->type == XML_ELEMENT_NODE) |
| count++; |
| xmlNode = xmlNode->next; |
| } |
| break; |
| case XML_COUNT_ATTR: |
| xmlAttr = ((xmlNodePtr) node)->properties; |
| while (xmlAttr) { |
| count++; |
| xmlAttr = xmlAttr->next; |
| } |
| break; |
| case XML_COUNT_NS: |
| xmlNode = (xmlNodePtr) node; |
| while (xmlNode != NULL) { |
| count += get_ns_count_at_node(xmlNode); |
| if (!bWalkUpTree) |
| break; |
| xmlNode = xmlNode->parent; |
| } |
| break; |
| default: |
| assert(what == XML_COUNT_NODE || what == XML_COUNT_ATTR || |
| what == XML_COUNT_NS); |
| break; |
| } |
| |
| return count; |
| } |
| |
| static xmlNodePtr |
| make_new_xml_node(xmlNodePtr base, |
| const char *uri, const char *name, const char *value, int xmlescape) |
| { |
| xmlNodePtr newNode = NULL; |
| xmlNsPtr ns = NULL; |
| if (uri == NULL || |
| (ns = |
| (xmlNsPtr) xml_parser_ns_find((WsXmlNodeH) base, uri, NULL, 1, |
| 1)) != NULL) { |
| if ((newNode = xmlNewNode(ns, BAD_CAST name)) != NULL) { |
| if (value != NULL){ |
| if (xmlescape == 1) |
| xmlNodeAddContent(newNode, BAD_CAST value); |
| else |
| xmlNodeSetContent(newNode, BAD_CAST value); |
| } |
| newNode->_private = u_zalloc(sizeof(iWsNode)); |
| } |
| } |
| return newNode; |
| } |
| |
| |
| |
| |
| |
| |
| WsXmlNodeH |
| xml_parser_node_add(WsXmlNodeH base, |
| int where, |
| const char *nsUri, |
| const char *localName, const char *value, int xmlescape) |
| { |
| xmlNodePtr xmlBase = (xmlNodePtr) base; |
| xmlNodePtr newNode = |
| make_new_xml_node((where != XML_ELEMENT_NEXT && |
| where != XML_ELEMENT_PREV) |
| ? xmlBase : xmlBase->parent, nsUri, |
| localName, value, xmlescape); |
| if (newNode) { |
| switch (where) { |
| case XML_ELEMENT_NEXT: |
| xmlAddNextSibling((xmlNodePtr) base, newNode); |
| break; |
| case XML_ELEMENT_PREV: |
| xmlAddPrevSibling((xmlNodePtr) base, newNode); |
| break; |
| case XML_LAST_CHILD: |
| default: |
| xmlAddChild((xmlNodePtr) base, newNode); |
| break; |
| } |
| } |
| return (WsXmlNodeH) newNode; |
| |
| } |
| |
| int xml_parser_node_remove(WsXmlNodeH node) |
| { |
| destroy_node_private_data(((xmlNodePtr) node)->_private); |
| xmlUnlinkNode((xmlNodePtr) node); |
| xmlFreeNode((xmlNodePtr) node); |
| return 0; |
| } |
| |
| |
| WsXmlAttrH |
| xml_parser_attr_add(WsXmlNodeH node, |
| const char *uri, const char *name, const char *value) |
| { |
| xmlNodePtr xmlNode = (xmlNodePtr) node; |
| xmlNsPtr xmlNs = |
| (xmlNsPtr) xml_parser_ns_find(node, uri, NULL, 1, 1); |
| xmlAttrPtr xmlAttr = |
| (xmlAttrPtr) ws_xml_find_node_attr(node, uri, name); |
| |
| if (xmlAttr != NULL) |
| ws_xml_remove_node_attr((WsXmlAttrH) xmlAttr); |
| |
| if (xmlNs == NULL) |
| xmlAttr = |
| xmlNewProp(xmlNode, BAD_CAST name, BAD_CAST value); |
| else |
| xmlAttr = |
| xmlNewNsProp(xmlNode, xmlNs, BAD_CAST name, |
| BAD_CAST value); |
| |
| if (xmlAttr != NULL) { |
| if (xmlNs == NULL) |
| xmlAttr->_private = |
| xmlGetProp(xmlNode, BAD_CAST name); |
| else |
| xmlAttr->_private = |
| xmlGetNsProp(xmlNode, BAD_CAST name, |
| xmlNs->href); |
| } |
| |
| return (WsXmlAttrH) xmlAttr; |
| } |
| |
| |
| |
| int xml_parser_attr_remove(WsXmlAttrH attr) |
| { |
| xmlAttrPtr xmlAttr = (xmlAttrPtr) attr; |
| xmlNodePtr xmlNode = (xmlNodePtr) xmlAttr->parent; |
| xmlAttrPtr xmlAttrPrev = |
| (xmlNode->properties == xmlAttr) ? NULL : xmlNode->properties; |
| |
| while (xmlAttrPrev != NULL && xmlAttrPrev->next != xmlAttr) { |
| xmlAttrPrev = xmlAttrPrev->next; |
| } |
| if (xmlAttrPrev != NULL) |
| xmlAttrPrev->next = xmlAttr->next; |
| else |
| xmlNode->properties = xmlAttr->next; |
| |
| xmlNode->parent = NULL; |
| xmlNode->next = NULL; |
| |
| destroy_attr_private_data((xmlAttrPtr) attr); |
| xmlFreeProp((xmlAttrPtr) attr); |
| |
| return 0; |
| } |
| |
| char *xml_parser_attr_query(WsXmlAttrH attr, int what) |
| { |
| char *ptr = NULL; |
| xmlAttrPtr xmlAttr = (xmlAttrPtr) attr; |
| switch (what) { |
| case XML_LOCAL_NAME: |
| ptr = (char *) xmlAttr->name; |
| break; |
| case XML_NS_URI: |
| if (xmlAttr->ns != NULL) |
| ptr = (char *) xmlAttr->ns->href; |
| break; |
| case XML_NS_PREFIX: |
| if (xmlAttr->ns != NULL) |
| ptr = (char *) xmlAttr->ns->prefix; |
| break; |
| case XML_TEXT_VALUE: |
| if (xmlAttr->_private == NULL) { |
| if (xmlAttr->ns == NULL) |
| xmlAttr->_private = |
| xmlGetProp(xmlAttr->parent, |
| xmlAttr->name); |
| else |
| xmlAttr->_private = |
| xmlGetNsProp(xmlAttr->parent, |
| xmlAttr->name, |
| xmlAttr->ns->href); |
| } |
| ptr = (char *) xmlAttr->_private; |
| break; |
| default: |
| assert(what == XML_LOCAL_NAME); |
| break; |
| } |
| return ptr; |
| } |
| |
| |
| |
| WsXmlAttrH xml_parser_attr_get(WsXmlNodeH node, int which) |
| { |
| xmlNodePtr xmlNode = (xmlNodePtr) node; |
| xmlAttrPtr xmlAttr = NULL; |
| |
| switch (which) { |
| case XML_LAST_CHILD: |
| default: |
| if (which >= 0 || which == XML_LAST_CHILD) { |
| int count = 0; |
| xmlAttr = xmlNode->properties; |
| |
| while (xmlAttr) { |
| if (which == XML_LAST_CHILD && |
| xmlAttr->next == NULL) |
| break; |
| |
| if (which == count) |
| break; |
| |
| count++; |
| |
| xmlAttr = xmlAttr->next; |
| } |
| } else { |
| assert(which >= 0 || which == XML_LAST_CHILD); |
| } |
| break; |
| } |
| |
| return (WsXmlAttrH) xmlAttr; |
| } |
| |
| |
| |
| void xml_parser_element_dump(FILE * f, WsXmlDocH doc, WsXmlNodeH node) |
| { |
| |
| xmlNodePtr n = (xmlNodePtr) node; |
| xmlDocPtr d = (xmlDocPtr) doc; |
| xmlElemDump(f, d, n); |
| } |
| |
| void xml_parser_doc_dump(FILE * f, WsXmlDocH doc) |
| { |
| |
| xmlDocPtr d = (xmlDocPtr) doc->parserDoc; |
| xmlDocFormatDump(f, d, 1); |
| return; |
| } |
| |
| void xml_parser_doc_dump_memory(WsXmlDocH doc, char **buf, int *ptrSize) |
| { |
| |
| xmlDocPtr d = (xmlDocPtr) doc->parserDoc; |
| xmlDocDumpFormatMemory(d, (xmlChar **) buf, ptrSize, 1); |
| return; |
| } |
| |
| static void |
| register_namespaces(xmlXPathContextPtr ctxt, WsXmlDocH doc, |
| WsXmlNodeH node) |
| { |
| xmlNsPtr *nsList, *cur; |
| xmlDocPtr d = (xmlDocPtr) doc->parserDoc; |
| |
| |
| nsList = xmlGetNsList(d, (xmlNodePtr) node); |
| if (nsList == NULL) { |
| return; |
| } |
| for (cur = nsList; *cur != NULL; cur++) { |
| if (xmlXPathRegisterNs(ctxt, (*cur)->prefix, (*cur)->href) |
| != 0) { |
| return; |
| } |
| } |
| xmlFree(nsList); |
| } |
| |
| |
| int xml_parser_check_xpath(WsXmlDocH doc, const char *expression) |
| { |
| xmlXPathObject *obj; |
| xmlNodeSetPtr nodeset; |
| xmlXPathContextPtr ctxt; |
| xmlDocPtr d = (xmlDocPtr) doc->parserDoc; |
| int retval = 0; |
| |
| ctxt = xmlXPathNewContext(d); |
| if (ctxt == NULL) { |
| error("failed while creating xpath context"); |
| return 0; |
| } |
| register_namespaces(ctxt, doc, xml_parser_get_root(doc)); |
| obj = xmlXPathEvalExpression(BAD_CAST expression, ctxt); |
| if (obj) { |
| nodeset = obj->nodesetval; |
| if (nodeset && nodeset->nodeNr > 0) { |
| int size = nodeset->nodeNr; |
| int i; |
| xmlNodePtr cur; |
| for(i = 0; i < size; ++i) { |
| if(nodeset->nodeTab[i]->type == XML_ELEMENT_NODE) { |
| cur = nodeset->nodeTab[i]; |
| if(cur->ns) { |
| fprintf(stdout, "= element node \"%s:%s\"\n", |
| cur->ns->href, cur->name); |
| } else { |
| fprintf(stdout, "= element node \"%s\"\n", |
| cur->name); |
| } |
| } |
| } |
| |
| retval = 1; |
| } |
| xmlXPathFreeContext(ctxt); |
| xmlXPathFreeObject(obj); |
| } else { |
| return 0; |
| } |
| |
| return retval; |
| } |
| |
| |
| |
| char *xml_parser_get_xpath_value(WsXmlDocH doc, const char *expression) |
| { |
| //int i; |
| char *result = NULL; |
| xmlXPathObject *obj; |
| xmlNodeSetPtr nodeset; |
| xmlXPathContextPtr ctxt; |
| xmlDocPtr d = (xmlDocPtr) doc->parserDoc; |
| WsXmlNodeH body; |
| |
| ctxt = xmlXPathNewContext(d); |
| if (ctxt == NULL) { |
| error("failed while creating xpath context"); |
| return NULL; |
| } |
| body = ws_xml_get_soap_body(doc); |
| register_namespaces(ctxt, doc, xml_parser_get_root(doc)); |
| if (ws_xml_get_child(body, 0, NULL, NULL)) { |
| register_namespaces(ctxt, doc, |
| ws_xml_get_child(body, 0, NULL, NULL)); |
| } |
| |
| obj = xmlXPathEvalExpression(BAD_CAST expression, ctxt); |
| if (obj) { |
| nodeset = obj->nodesetval; |
| if (nodeset && nodeset->nodeNr > 0) |
| result = (char *) xmlNodeListGetString(d, |
| nodeset-> |
| nodeTab[0]-> |
| xmlChildrenNode, |
| 1); |
| |
| xmlXPathFreeContext(ctxt); |
| xmlXPathFreeObject(obj); |
| } else { |
| return NULL; |
| } |
| |
| return result; |
| } |
| |
| |
| |
| void xml_parser_unlink_node(WsXmlNodeH node) |
| { |
| xmlUnlinkNode((xmlNodePtr) node); |
| xmlFreeNode((xmlNodePtr) node); |
| return; |
| } |
| |
| void xml_parser_node_set_lang(WsXmlNodeH node, const char *lang) |
| { |
| xmlNodeSetLang((xmlNodePtr) node, BAD_CAST lang); |
| } |
| |
| |
| void xml_parser_set_ns(WsXmlNodeH r, WsXmlNsH ns, const char *prefix) |
| { |
| xmlSetNs((xmlNodePtr) r, (xmlNsPtr) ns); |
| } |
| |
| void xml_parser_copy_node(WsXmlNodeH src, WsXmlNodeH dst) |
| { |
| if (src && dst) { |
| xmlNodePtr x = xmlDocCopyNode((xmlNodePtr) src, |
| ((xmlDocPtr) src)->doc, 1); |
| if (x) |
| xmlAddChild((xmlNodePtr) dst, x); |
| } |
| } |