Index: /trunk/psLib/src/xml/psXML.c
===================================================================
--- /trunk/psLib/src/xml/psXML.c	(revision 4785)
+++ /trunk/psLib/src/xml/psXML.c	(revision 4786)
@@ -1,30 +1,22 @@
 /** @file  psXML.c
 *
-*  @brief Contains XML input/output functions.
+*  @brief Contains basic XML definitions and operations
 *
-*  This file defines functions to read metadata from an XML file.
+*  This file defines the basic type for an XML struct and functions useful
+*  in creation and usage of XML documents/files.
 *
 *  @ingroup XML
 *
-*  @author Ross Harman, MHPCC
-*  @author Eric Van Alst, MHPCC
+*  @author David Robbins, MHPCC
 *
-*  @version $Revision: 1.35 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2005-07-12 19:12:01 $
+*  @version $Revision: 1.36 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2005-08-16 20:13:20 $
 *
 *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
 */
 
-#include <libxml/parser.h>
-#include <string.h>
-#include <ctype.h>
-#include <limits.h>
-
 #include "psXML.h"
-#include "psMemory.h"
-#include "psError.h"
-#include "psString.h"
-#include "psConstants.h"
-#include "psErrorText.h"
+#include <unistd.h>
+#include <fcntl.h>
 
 /******************************************************************************/
@@ -32,568 +24,519 @@
 /******************************************************************************/
 
-/** Maximum size of a FITS line */
-#define FITS_LINE_SIZE 80
-
 /** Maximum size of a string */
-#define MAX_STRING_LENGTH 256
-
-// Returns single parsed value as a double precision number. The input string must be cleaned and null
-// terminated.
-static double parseValue(char *inString, psS32 *status)
-{
-    char *end = NULL;
-    double value = 0.0;
-
-    value = strtod(inString, &end);
-    if(*end != '\0') {
-        *status = 1;
-    } else if(inString==end) {
-        *status = 1;
-    }
-
-    return value;
-}
-
-/** Returns true or false. 'T', 't', '1', 'F', 'f', and '0' are acceptable, parsable variations. */
-static psBool parseBool(char *inString, psS32 *status)
-{
-    psBool value = false;
-
-
-    if(*inString=='T' || *inString=='t' || *inString=='1') {
-        value = true;
-    } else if(*inString=='F' || *inString=='f' || *inString=='0') {
-        value = false;
-    } else {
-        *status = 1;
-    }
-
-    return value;
-}
-
-/** Returns parsed vector filled with with data. The input string must be null terminated. */
-static psVector* parseVector(char *inString, psElemType elemType, psS32 *status)
-{
-    char*      end       = NULL;
-    char*      saveValue = NULL;
-    psS32      i         = 0;
-    psS32      numValues = 0;
-    double     value     = 0.0;
-    psVector*  vec       = NULL;
-
-    // Cycle through string and count entries
-    saveValue = inString;
-    while(*inString!='\0') {
-        strtod(inString, &end);
-        if(inString==end) {
-            *status = 1;
+#define MAXSTR 256
+#define MAXVEC 2048
+#define MAXBUF 10000
+
+
+static void XMLFree(psXMLDoc *XML)
+{
+    xmlFreeDoc(*XML);
+}
+
+psXMLDoc *psXMLDocAlloc(void)
+{
+    psXMLDoc *XML;
+    XML = psAlloc(sizeof(psXMLDoc));
+    psMemSetDeallocator(XML, (psFreeFunc) XMLFree);
+    return(XML);
+}
+
+psXMLDoc *psMetadataToXMLDoc(const psMetadata *md)
+{
+    PS_ASSERT_PTR_NON_NULL(md, NULL);
+
+    psXMLDoc *XML = psXMLDocAlloc();
+    xmlNode *cur_node;
+    xmlNode *root = NULL;
+    xmlAttr *prop = NULL;
+    psDataType type;
+    char content[MAXSTR];
+    char vec[MAXVEC];
+    int i;
+    psMetadataIterator *iter = psMetadataIteratorAlloc(*(psMetadata**)&md, PS_LIST_HEAD, NULL);
+    psMetadataItem *item;
+
+    //setup root element
+    if( root == NULL ) {
+        *XML = xmlNewDoc((const xmlChar*)"1.0");
+        root = xmlNewDocNode(*XML, NULL, (const xmlChar*)"metadata", "\n");
+        xmlDocSetRootElement(*XML, root);
+    }
+    item = psMetadataGetAndIncrement(iter);
+    while ( item != NULL ) {
+        type = item->type;
+        if ( type == 65537)
+            type = PS_DATA_STRING;
+        if ( type == 65538)
+            type = PS_DATA_VECTOR;
+        if ( type == 65547)
+            type = PS_DATA_METADATA;
+        switch (type) {
+        case PS_DATA_BOOL:
+            cur_node = xmlNewChild(root, NULL, "item", "\n");
+            prop = xmlNewProp(cur_node, "name", item->name);
+            prop = xmlNewProp(cur_node, "psType", "BOOL");
+            if ( item->data.B )
+                strncpy(content, "TRUE", MAXSTR);
+            else
+                strncpy(content, "FALSE", MAXSTR);
+            prop = xmlNewProp(cur_node, "value", content);
+            break;
+        case PS_DATA_S32:
+            snprintf(content, MAXSTR, "%d", item->data.S32);
+            cur_node = xmlNewChild(root, NULL, "item", "\n");
+            prop = xmlNewProp(cur_node, "name", item->name);
+            prop = xmlNewProp(cur_node, "psType", "S32");
+            prop = xmlNewProp(cur_node, "value", content);
+            break;
+        case PS_DATA_F32:
+            snprintf(content, MAXSTR, "%f", item->data.F32);
+            cur_node = xmlNewChild(root, NULL, "item", "\n");
+            prop = xmlNewProp(cur_node, "name", item->name);
+            prop = xmlNewProp(cur_node, "psType", "F32");
+            prop = xmlNewProp(cur_node, "value", content);
+            break;
+        case PS_DATA_F64:
+            snprintf(content, MAXSTR, "%lf", item->data.F64);
+            cur_node = xmlNewChild(root, NULL, "item", "\n");
+            prop = xmlNewProp(cur_node, "name", item->name);
+            prop = xmlNewProp(cur_node, "psType", "F64");
+            prop = xmlNewProp(cur_node, "value", content);
+            break;
+        case PS_DATA_STRING:
+            cur_node = xmlNewChild(root, NULL, "item", "\n");
+            prop = xmlNewProp(cur_node, "name", item->name);
+            prop = xmlNewProp(cur_node, "psType", "STR");
+            strncpy(content, ((char *)(item->data.V)), MAXSTR);
+            prop = xmlNewProp(cur_node, "value", content);
+            break;
+        case PS_DATA_METADATA:
+            i = 0;
+            psXMLDoc *newDoc;
+            xmlNode *new_root = NULL;
+            xmlNode *new_node = NULL;
+            newDoc = psMetadataToXMLDoc(item->data.md);
+            new_root = xmlDocGetRootElement(*newDoc);
+            prop = xmlNewProp(new_root, "name", item->name);
+            prop = xmlNewProp(new_root, "psType", "METADATA");
+            new_node = xmlAddSibling(cur_node, new_root);
+            psFree(newDoc);
+            break;
+        case PS_DATA_VECTOR:
+            cur_node = xmlNewChild(root, NULL, "vector", "\n");
+            prop = xmlNewProp(cur_node, "name", item->name);
+            type = ((psVector*)(item->data.V))->type.type;
+            strncpy(vec, "", MAXSTR);
+            switch (type) {
+            case PS_DATA_S32:
+                prop = xmlNewProp(cur_node, "psType", "S32");
+                for (i = 0; ((psVector*)(item->data.V))->data.S32[i] != 0; i++) {
+                    snprintf(content, MAXSTR, "%d",
+                             ((psVector*)(item->data.V))->data.S32[i]);
+                    if ( ((psVector*)(item->data.V))->data.S32[i+1] != 0 ) {
+                        strncat(content, ", ", 2);
+                    }
+                    strncat(vec, content, MAXSTR);
+                }
+
+                break;
+            case PS_DATA_F32:
+                prop = xmlNewProp(cur_node, "psType", "F32");
+                for (i = 0; ((psVector*)(item->data.V))->data.F32[i] != 0; i++) {
+                    snprintf(content, MAXSTR, "%f",
+                             ((psVector*)(item->data.V))->data.F32[i]);
+                    if ( ((psVector*)(item->data.V))->data.F32[i+1] != 0 ) {
+                        strncat(content, ", ", 2);
+                    }
+                    strncat(vec, content, MAXSTR);
+                }
+                break;
+            case PS_DATA_F64:
+                prop = xmlNewProp(cur_node, "psType", "F64");
+                for (i = 0; ((psVector*)(item->data.V))->data.F64[i] != 0; i++) {
+                    snprintf(content, MAXSTR, "%lf",
+                             ((psVector*)(item->data.V))->data.F64[i]);
+                    if ( ((psVector*)(item->data.V))->data.F64[i+1] != 0 ) {
+                        strncat(content, ", ", 2);
+                    }
+                    strncat(vec, content, MAXSTR);
+                }
+                break;
+            case PS_DATA_UNKNOWN:
+            default:
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        PS_ERRORTEXT_psXML_INVALID_DATATYPE);
+                psFree(XML);
+                psFree(iter);
+                return NULL;
+            }
+            prop = xmlNewProp(cur_node, "value", vec);
+            break;
+        case PS_DATA_UNKNOWN:
+        default:
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    PS_ERRORTEXT_psXML_INVALID_DATATYPE);
+            psFree(XML);
+            psFree(iter);
             return NULL;
         }
-        while(*end==' ' || *end==',') { // Commas or spaces may be used as delimiters for vector values
-            end++;
-        }
-        inString=end;
-        numValues++;
-    }
-
-    // Cycle through string and convert string values to values
-    if(numValues) {
-        inString = saveValue;
-        end = NULL;
-        vec = psVectorAlloc(numValues, elemType);
-
-        while(*inString!='\0') {
-            value = strtod(inString, &end);
-            if(inString==end) {
-                *status = 1;
-                return vec;
-            }
-            switch(elemType) {
-            case PS_TYPE_U8:
-                vec->data.U8[i++] = (psU8)value;
-                break;
-            case PS_TYPE_U16:
-                vec->data.U16[i++] = (psU16)value;
-                break;
-            case PS_TYPE_U32:
-                vec->data.U32[i++] = (psU32)value;
-                break;
-            case PS_TYPE_U64:
-                vec->data.U64[i++] = (psU64)value;
-                break;
-            case PS_TYPE_S8:
-                vec->data.S8[i++] = (psS8)value;
-                break;
-            case PS_TYPE_S16:
-                vec->data.S16[i++] = (psS16)value;
-                break;
-            case PS_TYPE_S32:
-                vec->data.S32[i++] = (psS32)value;
-                break;
-            case PS_TYPE_S64:
-                vec->data.S64[i++] = (psS64)value;
-                break;
-            case PS_TYPE_F32:
-                vec->data.F32[i++] = (psF32)value;
-                break;
-            case PS_TYPE_F64:
-                vec->data.F64[i++] = (psF64)value;
-                break;
-            default:
-                *status = 1;
-                psError(PS_ERR_BAD_PARAMETER_VALUE,true,
-                        PS_ERRORTEXT_psMetadataIO_TYPE_INVALID,
-                        elemType);
-            }
-
-            while(*end==' ' || *end==',') {
-                end++;
-            }
-            inString=end;
-        }
-    }
-
-    return vec;
-}
-
-
-static void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts)
-{
-    psU64 i = 0;
-    char* psTagName = NULL;
-    char *psAttName = NULL;
-    char *psAttValue = NULL;
-    const xmlChar *attName = NULL;
-    const xmlChar *attValue = NULL;
-    psMetadata* md = NULL;
-    psHash* htAtts = NULL;
-    xmlParserCtxtPtr ctxt = NULL;
-    xmlParserInputPtr input = NULL;
-
-
-    // Get and check initial data pointers
-    ctxt = (xmlParserCtxtPtr)ctx;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(ctxt, return);
-    md = (psMetadata*)ctxt->sax->_private;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(md, return);
-    input = (xmlParserInputPtr)ctxt->input;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(input, return);
-
-    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
-    psTagName = psStringCopy((const char*)tagName);
-
-    // Metadata containter for housing element attributes used by other SAX events
-    htAtts = psHashAlloc(10);
-
-
-    // Get tag name
-    if(psTagName != NULL) {
-        psHashAdd(htAtts, "tagName", psTagName);
-    } else {
-        PS_ASSERT_GENERAL_PTR_NON_NULL(psTagName, return);
-        psFree(htAtts);
-        psFree(psTagName);
-        return;
-    }
-
-    // Get all attribute names and attribute values
-    if(atts != NULL) {
-        attName = atts[i++];
-        attValue = atts[i++];
-        while(attName != NULL) {
-            if(attValue != NULL) {
-
-                // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
-                psAttName = psStringCopy((const char*)attName);
-                psAttValue = psStringCopy((const char*)attValue);
-                psHashAdd(htAtts, psAttName, psAttValue);
-                psFree(psAttName);
-                psFree(psAttValue);
-            } else {
-                PS_ASSERT_GENERAL_PTR_NON_NULL(psAttValue, return);
-                psFree(htAtts);
-                psFree(psTagName);
-                return;
-            }
-            attName = atts[i++];
-            attValue = atts[i++];
-        }
-    }
-
-    // Add attributes to metadata
-
-    psMetadataAdd(md, PS_LIST_TAIL, "htAtts",
-                  PS_META_HASH | PS_META_DUPLICATE_OK,
-                  NULL, htAtts);
-
-    psFree(psTagName);
-    psFree(htAtts);
-
-    return;
-}
-
-static void initMetadataItemXml(void *ctx, char *tagName)
-{
-    psBool overwrite = false;
-    psBool tempBool = false;
-    psS32 status = 0;
-    psU32 lineNumber = 0;
-    psF64 tempDbl = 0.0;
-    psS32 tempInt = 0.0;
-    psMetadataType mdType = PS_META_UNKNOWN;
-    char *fileName = NULL;
-    char *strName = NULL;
-    char *strType = NULL;
-    char *strValue = NULL;
-    psMetadata* md = NULL;
-    psHash* htAtts = NULL;
-    psMetadataItem *metadataItem = NULL;
-    xmlParserCtxtPtr ctxt = NULL;
-    xmlParserInputPtr input = NULL;
-
-
-    // Get and check initial data pointers
-    ctxt = (xmlParserCtxtPtr)ctx;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(ctxt, return);
-    md = (psMetadata*)ctxt->sax->_private;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(md, return);
-    input = (xmlParserInputPtr)ctxt->input;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(input, return);
-    metadataItem = psMetadataLookup(md, "htAtts");
-    PS_ASSERT_GENERAL_PTR_NON_NULL(metadataItem, return);
-    PS_ASSERT_GENERAL_PTR_NON_NULL(metadataItem->data.list, return);
-    metadataItem = (psMetadataItem*)psListGet(metadataItem->data.list,PS_LIST_TAIL);
-    htAtts = (psHash*)metadataItem->data.list;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(htAtts, return);
-    fileName = (char*)input->filename;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(fileName, return);
-    lineNumber = input->line;
-
-    // Get attribute name
-    strName = psHashLookup(htAtts, "name");
-    if(strName == NULL) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_NO_NAME, lineNumber, fileName);
-        return;
-    }
-
-    // Get attribute type, if there is one
-    strType = psHashLookup(htAtts, "psType");
-    if(strType!= NULL) {
-        if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psString")) {
-            mdType = PS_META_STR;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
-            mdType = PS_META_BOOL;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
-            mdType = PS_META_S32;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
-            mdType = PS_META_F32;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
-            mdType = PS_META_F64;
-        } else {
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strType, lineNumber,
-                    fileName);
-            return;
-        }
-    }
-
-    // Get attribute value, if there is one
-    strValue = psHashLookup(htAtts, "value");
-
-    /* If metadata item is found, and is not a folder node, and overwrite is allowed, then remove
-    existing and allow switch/case below to add new item. If overwrite is false, then report error. If
-    found item is folder node, then psMetadataAdd will automatically add a new child. */
-    metadataItem = psMetadataLookup(md, "overwrite");
-    if(metadataItem != NULL) {
-        overwrite = parseBool((char*)strValue, &status);
-        if(status) {
-            status = 0;
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                    lineNumber, fileName);
-        }
-        metadataItem = psMetadataLookup(md, strName);
-        if(metadataItem != NULL) {
-            if(metadataItem->type != PS_META_LIST) {
-                if(overwrite) {
-                    psMetadataRemove(md, INT_MIN, strName);
-                } else {
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
-                            fileName);
-                    return;
-                }
-            }
-        }
-    }
-
-    // Create metadata item and add to metadata
-    switch(mdType) {
-    case PS_META_LIST:
-        psMetadataAdd(md, PS_LIST_TAIL, strName,
-                      mdType | PS_META_DUPLICATE_OK,
-                      NULL, NULL);
+        item = psMetadataGetAndIncrement(iter);
+    }
+    //    xmlSaveFormatFile("xmlfname", *XML, 1);
+    psFree(iter);
+    return XML;
+}
+
+//compares strings and returns the correct data type//
+static psDataType getType(const char *in)
+{
+    //Returns types S32, F32, F64, STRING, BOOL, or UNKNOWN on ERROR
+    if ( !strncmp(in, "S32", MAXSTR) ) {
+        return(PS_DATA_S32);
+    } else if ( !strncmp(in, "F32", MAXSTR) ) {
+        return(PS_DATA_F32);
+    } else if ( !strncmp(in, "F64", MAXSTR) ) {
+        return(PS_DATA_F64);
+    } else if ( !strncmp(in, "STR", MAXSTR) ) {
+        return(PS_DATA_STRING);
+    } else if ( !strncmp(in, "BOOL", MAXSTR) ) {
+        return(PS_DATA_BOOL);
+    }
+
+    return(PS_DATA_UNKNOWN);
+}
+
+static void storeValues(psVector *inVector, char *in, psDataType type)
+{
+    int i;
+    char *endp;
+
+    switch (type) {
+    case PS_DATA_S32:
+        i = 0;
+        int intValue = 0;
+        while (i < MAXSTR) {
+            intValue = (int)strtol(in, &endp, 10);
+            if ( intValue != 0 ) {
+                inVector->data.S32[i] = intValue;
+                i++;
+                while (!strncmp(endp, ",", 1))
+                    endp++;
+                in = endp;
+            } else
+                i = MAXSTR;
+        }
         break;
-    case PS_META_STR:
-        psMetadataAdd(md, PS_LIST_TAIL, strName,
-                      mdType | PS_META_DUPLICATE_OK,
-                      NULL, strValue);
+    case PS_DATA_F32:
+        i = 0;
+        float floatValue = 0.0;
+        while (i < MAXSTR) {
+            floatValue = strtof(in, &endp);
+            if ( floatValue != 0.0 ) {
+                inVector->data.F32[i] = floatValue;
+                i++;
+                while (!strncmp(endp, ",", 1))
+                    endp++;
+                in = endp;
+            } else
+                i = MAXSTR;
+        }
+
         break;
-    case PS_META_BOOL:
-        tempBool = parseBool((char*)strValue, &status);
-        if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName,
-                          mdType | PS_META_DUPLICATE_OK,
-                          NULL, tempBool);
-        } else {
-            status = 0;
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                    lineNumber, fileName);
-        }
-        break;
-    case PS_META_S32:
-        tempInt = (psS32)parseValue((char*)strValue, &status);
-        if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName,
-                          mdType | PS_META_DUPLICATE_OK,
-                          NULL, tempInt);
-        } else {
-            status = 0;
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                    lineNumber, fileName);
-        }
-        break;
-    case PS_META_F32:
-    case PS_META_F64:
-        tempDbl = parseValue((char*)strValue, &status);
-        if(!status) {
-            psMetadataAdd(md, PS_LIST_TAIL, strName,
-                          mdType | PS_META_DUPLICATE_OK,
-                          NULL, tempDbl);
-        } else {
-            status = 0;
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                    lineNumber, fileName);
+    case PS_DATA_F64:
+        i = 0;
+        double doubleValue = 0.0;
+        while (i < MAXSTR) {
+            doubleValue = strtod(in, &endp);
+            if ( doubleValue != 0.0 ) {
+                inVector->data.F64[i] = doubleValue;
+                i++;
+                while (!strncmp(endp, ",", 1))
+                    endp++;
+                in = endp;
+            } else
+                i = MAXSTR;
         }
         break;
     default:
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineNumber, fileName);
-    } // End switch
-
-    return;
-}
-
-
-static void initVectorXml(void *ctx, char *tagName)
-{
-    bool overwrite = false;
-    psS32 status = 0;
-    psU32 lineNumber = 0;
-    psElemType pType = 0;
-    char *strName = NULL;
-    char *strType = NULL;
-    char *strValue = NULL;
-    char *fileName = NULL;
-    psMetadataItem *table = NULL;
-    psMetadataItem *tables = NULL;
-    psMetadataItem *metadataItem = NULL;
-    psVector *vec = NULL;
-    psMetadata* md = NULL;
-    psHash* htAtts = NULL;
-    xmlParserCtxtPtr ctxt = NULL;
-    xmlParserInputPtr input = NULL;
-
-
-    // Get and check initial data pointers
-    ctxt = (xmlParserCtxtPtr)ctx;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(ctxt, return);
-    md = (psMetadata*)ctxt->sax->_private;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(md, return);
-    input = (xmlParserInputPtr)ctxt->input;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(input, return);
-    tables = psMetadataLookup(md, "htAtts");
-    PS_ASSERT_GENERAL_PTR_NON_NULL(tables, return);
-    PS_ASSERT_GENERAL_PTR_NON_NULL(tables->data.list, return);
-    table = (psMetadataItem*)psListGet(tables->data.list,PS_LIST_TAIL);
-    htAtts = (psHash*)table->data.list;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(htAtts, return);
-    fileName = (char*)input->filename;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(fileName, return);
-    lineNumber = input->line;
-
-    // Get attribute name
-    strName = psHashLookup(htAtts, "name");
-    if(strName == NULL) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_NO_NAME, lineNumber, fileName);
-        return;
-    }
-
-    // Get attribute type, if there is one
-    strType = psHashLookup(htAtts, "psType");
-    if(strType!= NULL) {
-        if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
-            pType = PS_TYPE_U8;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
-            pType = PS_TYPE_S32;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
-            pType = PS_TYPE_F32;
-        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
-            pType = PS_TYPE_F64;
+        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                PS_ERRORTEXT_psXML_INVALID_DATATYPE);
+    }
+}
+
+//Check the xml item for errors.  Returns the data type or PS_DATA_UNKNOWN for errors.//
+static psDataType chkType(xmlNode *node)
+{
+    //NEED TO CHECK CONTENTS OF EACH ITEM/NODE //
+    //if item then,
+    if(!strncmp(node->name, "item", MAXSTR) || !strncmp(node->name, "ITEM", MAXSTR)) {
+        if (node->properties != NULL && node->properties->name != NULL
+                && node->properties->next != NULL && node->properties->next->name != NULL
+                && node->properties->next->next != NULL
+                && node->properties->next->next->name != NULL) {
+            psDataType type = getType(node->properties->next->children->content);
+            return type;
         } else {
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strName, lineNumber,
-                    fileName);
-            return;
-        }
-    }
-
-    strValue = psHashLookup(htAtts, "value");
-    PS_ASSERT_GENERAL_PTR_NON_NULL(strValue, return);
-
-
-    /* If metadata item is found, and is not a folder node, and overwrite is allowed, then remove
-    existing and allow switch/case below to add new item. If overwrite is false, then report error. If
-    found item is folder node, then psMetadataAdd will automatically add a new child. */
-    metadataItem = psMetadataLookup(md, "overwrite");
-    if(metadataItem != NULL) {
-        overwrite = parseBool((char*)strValue, &status);
-        if(status) {
-            status = 0;
-            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                    input->line, input->filename);
-        }
-        metadataItem = psMetadataLookup(md, strName);
-        if(metadataItem != NULL) {
-            if(metadataItem->type != PS_META_LIST) {
-                if(overwrite) {
-                    psMetadataRemove(md, INT_MIN, strName);
-                } else {
-                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
-                            fileName);
-                    return;
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    PS_ERRORTEXT_psXML_INVALID_CONTENT);
+            return(PS_DATA_UNKNOWN);
+        }
+    }
+    //if vector then,
+    if(!strncmp(node->name, "vector", MAXSTR) || !strncmp(node->name, "VECTOR", MAXSTR)) {
+        if (node->properties != NULL && node->properties->name != NULL
+                && node->properties->next != NULL && node->properties->next->name != NULL
+                && node->properties->next->next != NULL
+                && node->properties->next->next->name != NULL) {
+            return(PS_DATA_VECTOR);
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    PS_ERRORTEXT_psXML_INVALID_CONTENT);
+            return(PS_DATA_UNKNOWN);
+        }
+
+    }
+    //if metadata then,
+    if(!strncmp(node->name, "metadata", MAXSTR)) {
+        if (node->properties != NULL && node->properties->name
+                && node->properties->next != NULL && node->properties->next->name != NULL) {
+            return(PS_DATA_METADATA);
+        } else {
+            psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                    PS_ERRORTEXT_psXML_INVALID_CONTENT);
+            return(PS_DATA_UNKNOWN);
+        }
+    }
+    return(PS_DATA_UNKNOWN);
+}
+
+//Sorts the xmlDocPtr data into a usable Metadata structure.  Transverses an xml tree.//
+static psMetadata *xml2metadata(xmlNode *nodePtr, int nodeNum)
+{
+    psMetadata *meta = NULL;
+    xmlNode *cur_node = NULL;
+    char name[MAXSTR];
+    char content[MAXSTR];
+    //    char *name = NULL;
+    //    char *content = NULL;
+    psDataType type = PS_DATA_UNKNOWN;
+    psDataType elemType = PS_DATA_UNKNOWN;
+
+    meta = psMetadataAlloc();
+    cur_node = nodePtr;
+
+    //    for ( cur_node = nodePtr; cur_node != NULL; cur_node = cur_node->next )
+    while (cur_node != NULL) {
+        if ( cur_node->type == XML_ELEMENT_NODE ) {
+            //if the root node isn't a metadata//
+            if ( nodeNum == 0 && strncmp(cur_node->name, "metadata", MAXSTR) ) {
+                psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                        PS_ERRORTEXT_psXML_INVALID_CONTENT);
+                psFree(meta);
+                return NULL;
+            }
+
+            if ( nodeNum != 0 ) {
+                type = chkType(cur_node);
+                //name = NULL;
+                //content = NULL;
+                switch ( type ) {
+                case PS_DATA_S32:
+                    strncpy(name, (char*)cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            (char*)cur_node->properties->next->next->children->content, MAXSTR);
+                    psMetadataAddS32(meta, PS_LIST_TAIL, name, "",
+                                     (int)strtol(content, NULL, 10));
+                    break;
+                case PS_DATA_F32:
+                    strncpy(name, cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            cur_node->properties->next->next->children->content, MAXSTR);
+                    psMetadataAddF32(meta, PS_LIST_TAIL, name, "", strtof(content, NULL));
+                    break;
+                case PS_DATA_F64:
+                    strncpy(name, cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            cur_node->properties->next->next->children->content, MAXSTR);
+                    psMetadataAddF64(meta, PS_LIST_TAIL, name, "", strtod(content, NULL));
+                    break;
+                case PS_DATA_STRING:
+                    strncpy(name, cur_node->properties->children->content, MAXSTR);
+                    psMetadataAddStr(meta, PS_LIST_TAIL, name, "",
+                                     cur_node->properties->next->next->children->content);
+                    break;
+                case PS_DATA_VECTOR:
+                    strncpy(name, cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            cur_node->properties->next->next->children->content, MAXSTR);
+                    elemType = getType(cur_node->properties->next->children->content);
+                    if (elemType == PS_DATA_UNKNOWN || elemType == PS_DATA_STRING
+                            || elemType == PS_DATA_BOOL) {
+                        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                                PS_ERRORTEXT_psXML_INVALID_DATATYPE);
+                        psFree(meta);
+                        return NULL;
+                    }
+
+                    psVector *vec = psVectorAlloc(strlen(content), elemType);
+                    storeValues(vec, content, elemType);
+                    psMetadataAddVector(meta, PS_LIST_TAIL, name, "", vec);
+                    psFree(vec);
+                    break;
+                case PS_DATA_METADATA:
+                    strncpy(name, cur_node->properties->children->content, MAXSTR);
+                    //                        psMetadata *temp = psMetadataAlloc();
+                    psMetadata *temp = NULL;
+                    temp = xml2metadata(cur_node->children, nodeNum);
+                    psMetadataAddMetadata(meta, PS_LIST_TAIL, name, "", temp);
+                    psFree(temp);
+                    break;
+                case PS_DATA_BOOL:
+                    strncpy(name, cur_node->properties->children->content, MAXSTR);
+                    strncpy(content,
+                            cur_node->properties->next->next->children->content, MAXSTR);
+                    if ( !strncmp(content, "true", MAXSTR) ||
+                            !strncmp(content, "TRUE", MAXSTR) ||
+                            !strncmp(content, "T", MAXSTR) ||
+                            !strncmp(content, "t", MAXSTR) ) {
+                        psMetadataAddBool(meta, PS_LIST_TAIL, name, "", true);
+                    } else if ( !strncmp(content, "false", MAXSTR) ||
+                                !strncmp(content, "FALSE", MAXSTR) ||
+                                !strncmp(content, "F", MAXSTR) ||
+                                !strncmp(content, "f", MAXSTR) ) {
+                        psMetadataAddBool(meta, PS_LIST_TAIL, name, "", false);
+                    } else {
+                        psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                                PS_ERRORTEXT_psXML_INVALID_CONTENT);
+                        psFree(meta);
+                        return NULL;
+                    }
+                    break;
+                case PS_DATA_UNKNOWN:
+                default:
+                    psError(PS_ERR_BAD_PARAMETER_VALUE, true,
+                            PS_ERRORTEXT_psXML_INVALID_DATATYPE);
+                    psFree(meta);   //XXX: Do I really need this?
+                    return NULL;
                 }
+                nodeNum++;
+            } else //if root node, then increment nodeNum and go to children//
+            {
+                nodeNum++;
+                cur_node = cur_node->children;
             }
         }
-    }
-
-    // Get value
-    vec = parseVector((char*)strValue, pType, &status);
-    if(!status) {
-        psMetadataAdd(md, PS_LIST_TAIL, strName+1,
-                      PS_META_VEC | PS_META_DUPLICATE_OK,
-                      NULL, vec);
-    } else {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
-                lineNumber, fileName);
-    }
-    psFree(vec);
-}
-
-static void saxEndElement(void *ctx, const xmlChar *tagName)
-{
-    char *psStartTagName = NULL;
-    char *psEndTagName = NULL;
-    psMetadata* md = NULL;
-    psHash* htAtts = NULL;
-    psMetadataItem *table = NULL;
-    psMetadataItem *tables = NULL;
-    xmlParserCtxtPtr ctxt = NULL;
-    xmlParserInputPtr input = NULL;
-
-
-    // Get and check initial data pointers
-    ctxt = (xmlParserCtxtPtr)ctx;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(ctxt, return);
-    md = (psMetadata*)ctxt->sax->_private;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(md, return);
-    input = (xmlParserInputPtr)ctxt->input;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(input, return);
-    tables = psMetadataLookup(md, "htAtts");
-    PS_ASSERT_GENERAL_PTR_NON_NULL(tables, return);
-    PS_ASSERT_GENERAL_PTR_NON_NULL(tables->data.list, return);
-    table = (psMetadataItem*)psListGet(tables->data.list,PS_LIST_TAIL);
-    htAtts = (psHash*)table->data.list;
-    PS_ASSERT_GENERAL_PTR_NON_NULL(htAtts, return);
-
-    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
-    psEndTagName = psStringCopy((const char*)tagName);
-
-    // Compare start and end tag names
-    psStartTagName = psHashLookup(htAtts, "tagName");
-    PS_ASSERT_GENERAL_PTR_NON_NULL(psStartTagName, return);
-    if(strcmp(psEndTagName, psStartTagName)) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TAG_MISMATCH, psStartTagName, psEndTagName);
-    }
-
-    // Initialize psLib structs
-    if(!strcmp(psEndTagName, "psMetadataItem")) {
-        initMetadataItemXml(ctx, psEndTagName);
-    } else if(!strcmp(psEndTagName, "psVector")) {
-        initVectorXml(ctx, psEndTagName);
-    } else if(strcmp(psEndTagName, "psRoot")) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TAG_UNKNOWN, psEndTagName);
-    }
-
-    // Free temporary metadata item and its hash table
-    psListRemove(tables->data.list, PS_LIST_TAIL);
-
-    psFree(psEndTagName);
-
-    return;
-}
-
-psMetadata*  psMetadataConfigParseXml(psMetadata* md, psU32 *nFail, const char *fileName, psBool overwrite)
-{
-    xmlSAXHandler saxHandler;
-
-
-    // Error checks
-    PS_ASSERT_PTR_NON_NULL(fileName, NULL);
-
-    // Allocate metadata if necessary
-    if (md == NULL) {
-        md = psMetadataAlloc();
-    }
-
-    // Sax handler initializations
-    saxHandler.internalSubset           = NULL;
-    saxHandler.isStandalone             = NULL;
-    saxHandler.hasInternalSubset        = NULL;
-    saxHandler.hasExternalSubset        = NULL;
-    saxHandler.resolveEntity            = NULL;
-    saxHandler.getEntity                = NULL;
-    saxHandler.entityDecl               = NULL;
-    saxHandler.notationDecl             = NULL;
-    saxHandler.attributeDecl            = NULL;
-    saxHandler.elementDecl              = NULL;
-    saxHandler.unparsedEntityDecl       = NULL;
-    saxHandler.setDocumentLocator       = NULL;
-    saxHandler.startDocument            = NULL;
-    saxHandler.endDocument              = NULL;
-    saxHandler.startElement             = saxStartElement;
-    saxHandler.endElement               = saxEndElement;
-    saxHandler.reference                = NULL;
-    saxHandler.characters               = NULL;
-    saxHandler.ignorableWhitespace      = NULL;
-    saxHandler.processingInstruction    = NULL;
-    saxHandler.comment                  = NULL;
-    saxHandler.warning                  = xmlParserError;
-    saxHandler.error                    = xmlParserError;
-    saxHandler.fatalError               = xmlParserError;
-    saxHandler.getParameterEntity       = NULL;
-    saxHandler.cdataBlock               = NULL;
-    saxHandler.externalSubset           = NULL;
-    saxHandler.initialized              = 1;
-    saxHandler._private                 = md;
-    saxHandler.startElementNs           = NULL;
-    saxHandler.endElementNs             = NULL;
-    saxHandler.serror                   = NULL;
-
-    // Parse XML file
-    if (xmlSAXUserParseFile(&saxHandler, NULL, fileName)) {
-        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_OPEN_FAILED, fileName);
-        return NULL;
-    }
-
-    // Parser and memory cleanups for libxml2
+        cur_node = cur_node->next;
+    }
+    psFree(cur_node);
+    return meta;
+}
+
+psMetadata *psXMLDocToMetadata(const psXMLDoc *doc)
+{
+    PS_ASSERT_PTR_NON_NULL(doc, NULL);
+    //    psMetadata *md = psMetadataAlloc();
+    psMetadata *md = NULL;
+    xmlNode *root_element = NULL;
+    //XXX: doc changed to *doc
+    root_element = xmlDocGetRootElement(*doc);
+    md = xml2metadata(root_element, 0);
+    return md;
+}
+
+psXMLDoc *psXMLParseFile(const char *filename)
+{
+
+    PS_ASSERT_PTR_NON_NULL(filename, NULL);
+    psXMLDoc *XML;
+    XML = psXMLDocAlloc();
+    *XML = xmlReadFile(filename, NULL, 0);
+
     xmlCleanupParser();
     xmlMemoryDump();
-
-    return md;
-}
+    return XML;
+}
+
+bool psXMLDocToFile(const psXMLDoc *doc,
+                    const char *filename)
+{
+    PS_ASSERT_PTR_NON_NULL(doc, 0);
+    PS_ASSERT_PTR_NON_NULL(filename, 0);
+    FILE *file;
+    if( (file = fopen(filename, "w")) == NULL ) {
+        psError(PS_ERR_IO, true, PS_ERRORTEXT_psXML_IO_FILE_OPEN_FAILED, filename);
+        return false;
+    }
+
+    xmlDocDump(file, *doc);
+    fclose(file);
+    return true;
+}
+
+psXMLDoc *psXMLParseMem(const char *buffer,
+                        int size)
+{
+    PS_ASSERT_PTR_NON_NULL(buffer, NULL);
+    PS_ASSERT_INT_NONZERO(size, NULL);
+    char *URL = "new.xml";
+    psXMLDoc *XML;
+    XML = psXMLDocAlloc();
+    *XML = xmlReadMemory(buffer, size, URL, NULL, 0);
+
+    xmlCleanupParser();
+    xmlMemoryDump();
+
+    return XML;
+}
+
+bool psXMLDocToMem(const psXMLDoc *doc,
+                   char *buffer)
+{
+    PS_ASSERT_PTR_NON_NULL(doc, 0);
+    int bufferSize;
+    xmlChar *buff;
+
+    xmlDocDumpMemory(*doc, &buff, &bufferSize);
+    if ( MAXVEC < strlen((char *)buff) ) {
+        psError(PS_ERR_LOCATION_INVALID, true, PS_ERRORTEXT_psXML_BUFFER_TOO_SMALL);
+        //        xmlFree(buff);
+        return false;
+    }
+    strncpy(buffer, buff, MAXVEC);
+    xmlFree(buff);
+
+    return true;
+}
+
+psXMLDoc *psXMLParseFD(int fd)
+{
+    PS_ASSERT_INT_NONNEGATIVE(fd, NULL);
+    char *URL = "new.xml";
+    psXMLDoc *XML;
+    XML = psXMLDocAlloc();
+    *XML = xmlReadFd(fd, URL, NULL, 0);
+
+    xmlCleanupParser();
+    xmlMemoryDump();
+
+    return XML;
+}
+
+bool psXMLDocToFD(const psXMLDoc *doc,
+                  int fd)
+{
+    PS_ASSERT_PTR_NON_NULL(doc, 0);
+    PS_ASSERT_INT_NONNEGATIVE(fd, 0);
+
+    char buf[MAXBUF];
+    int n;
+    if ( psXMLDocToMem(doc, buf) ) {
+        n = strlen(buf);
+        write(fd, buf, n);
+    } else {
+        psError(PS_ERR_LOCATION_INVALID, true, PS_ERRORTEXT_psXML_BUFFER_TOO_SMALL);
+        return false;
+    }
+    return true;
+}
Index: /trunk/psLib/src/xml/psXML.h
===================================================================
--- /trunk/psLib/src/xml/psXML.h	(revision 4785)
+++ /trunk/psLib/src/xml/psXML.h	(revision 4786)
@@ -1,32 +1,123 @@
 /** @file  psXML.h
  *
- *  @brief Contains XML functions.
+ *  @brief Contains basic XML definitions and operations
  *
- *  This file defines functions to read metadata from an XML file.
+ *  This file defines the basic type for an XML struct and functions useful
+ *  in creation and usage of XML documents/files.
  *
  *  @ingroup XML
  *
- *  @author Ross Harman, MHPCC
- *  @author Robert DeSonia, MHPCC
+ *  @author David Robbins, MHPCC
  *
- *  @version $Revision: 1.16 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2005-07-12 19:12:01 $
+ *  @version $Revision: 1.17 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2005-08-16 20:13:20 $
  *
- *  Copyright 2004-2005 Maui High Performance Computing Center, University of Hawaii
+ *  Copyright 2005 Maui High Performance Computing Center, University of Hawaii
  */
+
 #ifndef PS_XML_H
 #define PS_XML_H
 
+//#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+
 #include "psMetadata.h"
 #include "psMetadataConfig.h"
+#include "psMemory.h"
+#include "psError.h"
+#include "psString.h"
+#include "psConstants.h"
+#include "psErrorText.h"
+
 
 /// @addtogroup XML
 /// @{
 
-psMetadata*  psMetadataConfigParseXml(
-    psMetadata* md,                    ///< Resulting metadata from read.
-    psU32 *nFail,                      ///< Number of failed lines.
-    const char *fileName,              ///< Name of file to read.
-    psBool overwrite                   ///< Allow overwrite of duplicate specifications.
+/** XML wrapper pointing to an XML document in memory */
+typedef xmlDocPtr psXMLDoc;
+
+
+/*****************************************************************************/
+
+/* FUNCTION PROTOTYPES                                                       */
+
+/*****************************************************************************/
+
+/** Allocates a new psXMLDoc
+ *
+ *  @return psXMLDoc*         a new psXMLDoc object
+*/
+psXMLDoc *psXMLDocAlloc(void);
+
+/** Converts a psMetadata data structure to a complete psXMLDoc (in memory)
+ *
+ *  @return psXMLDoc*           Pointer to XML document from read
+*/
+psXMLDoc *psMetadataToXMLDoc(
+    const psMetadata *md               ///< psMetadata structure to read
+);
+
+/** Converts a complete psXMLDoc (in memory) to a psMetadata data structure
+ *
+ *  @return psMetadata*         Pointer to psMetadata data structure from read
+*/
+psMetadata *psXMLDocToMetadata(
+    const psXMLDoc *doc                ///< psXMLDoc to read
+);
+
+/** Loads the data in a named file into a complete psXMLDoc (in memory)
+ *
+ *  @return psXMLDoc*       Pointer to resulting XML document from read
+*/
+psXMLDoc *psXMLParseFile(
+    const char *filename               ///< Filename of file to be read
+);
+
+/** Writes out a complete psXMLDoc (in memory) to a named file
+ *
+ *  @return bool:       True on success or false otherwise.
+*/
+bool psXMLDocToFile(
+    const psXMLDoc *doc,               ///< psXMLDoc to read
+    const char *filename               ///< Filename of file to be written
+);
+
+/** Accepts a block of memory and parses it into a complete psXMLDoc (also in memory)
+ *
+ *  @return psXMLDoc*       Pointer to resulting XML document from read
+*/
+psXMLDoc *psXMLParseMem(
+    const char *buffer,                ///< Buffer to read
+    int size                           ///< Size of buffer
+);
+
+/** Accepts a complete psXMLDoc (in memory) and parses it into a block of memory
+ *
+ *  @return bool:       True on success or false otherwise.
+*/
+bool psXMLDocToMem(
+    const psXMLDoc *doc,               ///< psXMLDoc to read
+    char *buffer                       ///< Buffer to write
+);
+
+/** Reads from a file descriptor and converts the incoming data to a complete
+ *  psXMLDoc (in memory)
+ *
+ *  @return psXMLDoc*      Pointer to resulting XML document from read
+*/
+psXMLDoc *psXMLParseFD(
+    int fd                             ///< File descriptor to read
+);
+
+/** Reads from a complete psXMLDoc (in memory) and writes it to a file descriptor
+ *
+ *  @return bool:       True on success or false otherwise.
+*/
+bool psXMLDocToFD(
+    const psXMLDoc *doc,               ///< psXMLDoc to read
+    int fd                             ///< File descriptor to write
 );
 
@@ -34,2 +125,3 @@
 
 #endif // #ifndef PS_XML_H
+
