Index: /trunk/psLib/src/astronomy/Makefile
===================================================================
--- /trunk/psLib/src/astronomy/Makefile	(revision 2520)
+++ /trunk/psLib/src/astronomy/Makefile	(revision 2521)
@@ -6,5 +6,6 @@
 include ../Makefile.Globals
 CFLAGS := $(CFLAGS_RELOC) -I. -I../sysUtils -I../collections -I../dataManip \
-    -I.. -I../image -I../fileUtils -DTIME_CONFIG_FILE="\"$(TIME_CONFIG_FILE)\""
+    -I.. -I../image -I../fileUtils -I/usr/include/libxml2 \
+    -DTIME_CONFIG_FILE="\"$(TIME_CONFIG_FILE)\""
 
 SRC_OBJS = psTime.o \
Index: /trunk/psLib/src/astronomy/psAstronomyErrors.h
===================================================================
--- /trunk/psLib/src/astronomy/psAstronomyErrors.h	(revision 2520)
+++ /trunk/psLib/src/astronomy/psAstronomyErrors.h	(revision 2521)
@@ -7,6 +7,6 @@
  *  @author Robert DeSonia, MHPCC
  *
- *  @version $Revision: 1.5 $ $Name: not supported by cvs2svn $
- *  @date $Date: 2004-11-16 20:00:20 $
+ *  @version $Revision: 1.6 $ $Name: not supported by cvs2svn $
+ *  @date $Date: 2004-11-30 00:25:50 $
  *
  *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -54,5 +54,5 @@
 #define PS_ERRORTEXT_psCoord_UNITS_UNKNOWN "Specified units, 0x%x, is not supported."
 #define PS_ERRORTEXT_psCoord_OFFSET_MODE_UNKNOWN "Specified offset mode, 0x%x, is not supported."
-#define PS_ERRORTEXT_psAstrometry_NONLINEAR_TRANSFORM "The %s transfrom is not linear.  Only linear transforms are supported. "
+#define PS_ERRORTEXT_psAstrometry_NONLINEAR_TRANSFORM "The %s transfrom is not linear.  Only linear transforms are supported."
 #define PS_ERRORTEXT_psMetadata_METATYPE_INVALID "Specified psMetadataType, %d, is not supported."
 #define PS_ERRORTEXT_psMetadata_ADD_LIST_FAILED "Failed to add metadata item, %s, to items list."
@@ -66,13 +66,17 @@
 #define PS_ERRORTEXT_psMetadata_FIND_INDEX_FAILED "Could not find metadata item at index %d."
 #define PS_ERRORTEXT_psMetadataIO_TYPE_INVALID "Specified type, %d, is not supported."
+#define PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE "Specified type, %s, is not supported on line %lld of %s"
 #define PS_ERRORTEXT_psMetadataIO_EXTNUM_NOTPOSITIVE "Specified extension number, %d, is invalid.  Value must be positive if no extension name is given."
 #define PS_ERRORTEXT_psMetadataIO_FITS_METATYPE_INVALID "Specified FITS metadata type, %c, is not supported."
 #define PS_ERRORTEXT_psMetadataIO_ADD_FAILED "Failed to add metadata item, %s."
-#define PS_ERRORTEXT_psMetadataIO_FILE_OPEN_FAILED "Failed to open file '%s'.  Check if it exists and it has the proper permissions."
+#define PS_ERRORTEXT_psMetadataIO_FILE_OPEN_FAILED "Failed to open file '%s'. Check if it exists and it has the proper permissions."
 #define PS_ERRORTEXT_psMetadataIO_FILE_MULTIPLE_CHAR "More than one '%c' character not allowed.  Found on line %d of %s."
-#define PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL "Failed to read a metadata %s on line %d of %s."
-#define PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID "Metadata type '%s', found on line %d of %s, is not invalid."
-#define PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM "Duplicate Metadata item, %s, found on line %d of %s.  Overwrite not allowed."
-#define PS_ERRORTEXT_psMetadataIO_PARSE_FAILED "Failed to parse the value '%s' of metadata item %s, type %s, on line %d of %s."
+#define PS_ERRORTEXT_psMetadataIO_FILE_ELEMENT_NULL "Failed to read a metadata %s on line %lld of %s."
+#define PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID "Metadata type '%s', found on line %lld of %s, is not invalid."
+#define PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM "Duplicate Metadata item, %s, found on line %lld of %s.  Overwrite not allowed."
+#define PS_ERRORTEXT_psMetadataIO_PARSE_FAILED "Failed to parse the value '%s' of metadata item %s, type %s, on line %lld of %s."
+#define PS_ERRORTEXT_psMetadataIO_NO_NAME "Couldn't find XML name attribute on line %lld of %s."
+#define PS_ERRORTEXT_psMetadataIO_TAG_MISMATCH "Start and end tag names don't agree, start tag, %s end tag, %s"
+#define PS_ERRORTEXT_psMetadataIO_TAG_UNKNOWN "Unknown tag name, %s"
 //~End
 
Index: /trunk/psLib/src/astronomy/psMetadata.c
===================================================================
--- /trunk/psLib/src/astronomy/psMetadata.c	(revision 2520)
+++ /trunk/psLib/src/astronomy/psMetadata.c	(revision 2521)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.37 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-11-09 00:36:13 $
+*  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-11-30 00:26:53 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -82,5 +82,6 @@
     psFree(metadataItem->items);
     if (type == PS_META_STR || type == PS_META_VEC || type == PS_META_IMG || type == PS_META_LOOKUPTABLE ||
-            type == PS_META_JPEG || type == PS_META_PNG || type == PS_META_ASTROM || type == PS_META_UNKNOWN) {
+            type == PS_META_JPEG || type == PS_META_PNG || type == PS_META_ASTROM || type == PS_META_UNKNOWN ||
+            type == PS_META_HASH) {
         psFree(metadataItem->data.V);
     }
@@ -183,4 +184,7 @@
     case PS_META_LOOKUPTABLE:
         metadataItem->data.V = va_arg(argPtr, psLookupTable*); // Deep copy of input data not performed
+        break;
+    case PS_META_HASH:
+        metadataItem->data.V = va_arg(argPtr, psHash*); // Deep copy of input data not performed
         break;
     case PS_META_IMG:
@@ -211,5 +215,4 @@
     // Allocate metadata's internal containers
     list = (psList* ) psListAlloc(NULL);
-
     table = (psHash* ) psHashAlloc(10);
 
Index: /trunk/psLib/src/astronomy/psMetadata.h
===================================================================
--- /trunk/psLib/src/astronomy/psMetadata.h	(revision 2520)
+++ /trunk/psLib/src/astronomy/psMetadata.h	(revision 2521)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-11-09 00:36:13 $
+*  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-11-30 00:27:14 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -40,4 +40,5 @@
     PS_META_STR,                       ///< String data (Stored in as psPtr ).
     PS_META_VEC,                       ///< Vector data (Stored in as psPtr ).
+    PS_META_HASH,                      ///< Hash data (Stored in as psPtr ).
     PS_META_IMG,                       ///< Image data (Stored in as psPtr ).
     PS_META_LOOKUPTABLE,               ///< Lookup table data (Stored as void *).
Index: /trunk/psLib/src/astronomy/psMetadataIO.c
===================================================================
--- /trunk/psLib/src/astronomy/psMetadataIO.c	(revision 2520)
+++ /trunk/psLib/src/astronomy/psMetadataIO.c	(revision 2521)
@@ -9,10 +9,11 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-11-10 18:26:46 $
+*  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-11-30 00:27:40 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */
 
+#include <libxml/parser.h>
 #include <fitsio.h>
 #include <string.h>
@@ -32,4 +33,10 @@
 #include "psAstronomyErrors.h"
 
+
+typedef struct
+{
+    int y;
+}
+myStruct;
 
 /******************************************************************************/
@@ -103,4 +110,8 @@
 /*****************************************************************************/
 
+void p_saxEndElement(void *ctx, const xmlChar *tagName);
+void p_psInitVectorXml(void *ctx, char *tagName);
+void p_psInitMetadataItemXml(void *ctx, char *tagName);
+void p_saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts);
 
 /** Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
@@ -329,7 +340,5 @@
         break;
     default:
-        psError(PS_ERR_BAD_PARAMETER_TYPE,true,
-                PS_ERRORTEXT_psMetadata_METATYPE_INVALID,
-                (int)type);
+        psError(PS_ERR_BAD_PARAMETER_TYPE,true, PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type);
     }
 }
@@ -680,2 +689,448 @@
     return failedLines;
 }
+
+void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts)
+{
+    psU64 i = 0;
+    psU64 lineNumber = 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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+
+    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
+    psTagName = psStringCopy(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_PTR_CHECK_NULL_GENERAL(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(attName);
+                psAttValue = psStringCopy(attValue);
+                psHashAdd(htAtts, psAttName, psAttValue);
+                psFree(psAttName);
+                psFree(psAttValue);
+            } else {
+                PS_PTR_CHECK_NULL_GENERAL(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, NULL, htAtts);
+
+    psFree(psTagName);
+
+    return;
+}
+
+void p_psInitMetadataItemXml(void *ctx, char *tagName)
+{
+    psBool overwrite = false;
+    psBool tempBool = false;
+    psS32 status = 0;
+    psU64 lineNumber = 0;
+    psF64 tempDbl = 0.0;
+    psS32 tempInt = 0.0;
+    psElemType elemType;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    metadataItem = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(metadataItem, return);
+    PS_PTR_CHECK_NULL_GENERAL(metadataItem->items, return);
+    psListSetIterator(metadataItem->items, PS_LIST_TAIL);
+    metadataItem = (psMetadataItem*)psListGetCurrent(metadataItem->items);
+    htAtts = (psHash*)metadataItem->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+    fileName = (char*)input->filename;
+    PS_PTR_CHECK_NULL_GENERAL(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;
+            elemType = PS_TYPE_PTR;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
+            mdType = PS_META_BOOL;
+            elemType = PS_TYPE_U8;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
+            mdType = PS_META_S32;
+            elemType = PS_TYPE_S32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
+            mdType = PS_META_F32;
+            elemType = PS_TYPE_F32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
+            mdType = PS_META_F64;
+            elemType = PS_TYPE_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_ITEM_SET) {
+                if(overwrite) {
+                    psMetadataRemove(md, PS_LIST_UNKNOWN, 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_ITEM_SET:
+        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
+        break;
+    case PS_META_BOOL:
+        tempBool = parseBool((char*)strValue, &status);
+        if(!status) {
+            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, 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, 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, NULL, tempDbl);
+        } else {
+            status = 0;
+            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
+                    lineNumber, fileName);
+        }
+        break;
+    case PS_META_STR:
+        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, strValue);
+        break;
+    default:
+        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineNumber, fileName);
+    } // End switch
+
+    return;
+}
+
+
+void p_psInitVectorXml(void *ctx, char *tagName)
+{
+    bool overwrite = false;
+    psS32 status = 0;
+    psU64 lineNumber = 0;
+    psElemType elemType;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    tables = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(tables, return);
+    PS_PTR_CHECK_NULL_GENERAL(tables->items, return);
+    psListSetIterator(tables->items, PS_LIST_TAIL);
+    table = (psMetadataItem*)psListGetCurrent(tables->items);
+    htAtts = (psHash*)table->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+    fileName = (char*)input->filename;
+    PS_PTR_CHECK_NULL_GENERAL(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;
+            elemType = PS_TYPE_PTR;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
+            mdType = PS_META_BOOL;
+            elemType = PS_TYPE_U8;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
+            mdType = PS_META_S32;
+            elemType = PS_TYPE_S32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
+            mdType = PS_META_F32;
+            elemType = PS_TYPE_F32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
+            mdType = PS_META_F64;
+            elemType = PS_TYPE_F64;
+        } else {
+            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strName, lineNumber,
+                    fileName);
+            return;
+        }
+    }
+
+    strValue = psHashLookup(htAtts, "value");
+    PS_PTR_CHECK_NULL_GENERAL(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_ITEM_SET) {
+                if(overwrite) {
+                    psMetadataRemove(md, PS_LIST_UNKNOWN, strName);
+                } else {
+                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
+                            fileName);
+                    return;
+                }
+            }
+        }
+    }
+
+    // Get value
+    vec = parseVector((char*)strValue, elemType, &status);
+    if(!status) {
+        psMetadataAdd(md, PS_LIST_TAIL, strName+1, mdType, NULL, vec);
+    } else {
+        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
+                lineNumber, fileName);
+    }
+    psFree(vec);
+}
+
+void saxEndElement(void *ctx, const xmlChar *tagName)
+{
+    psU64 lineNumber = 0;
+    char *psStartTagName = NULL;
+    char *psEndTagName = NULL;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    tables = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(tables, return);
+    PS_PTR_CHECK_NULL_GENERAL(tables->items, return);
+    psListSetIterator(tables->items, PS_LIST_TAIL);
+    table = (psMetadataItem*)psListGetCurrent(tables->items);
+    htAtts = (psHash*)table->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+
+    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
+    psEndTagName = psStringCopy(tagName);
+
+    // Compare start and end tag names
+    psStartTagName = psHashLookup(htAtts, "tagName");
+    PS_PTR_CHECK_NULL_GENERAL(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")) {
+        p_psInitMetadataItemXml(ctx, psEndTagName);
+    } else if(!strcmp(psEndTagName, "psVector")) {
+        p_psInitVectorXml(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->items, PS_LIST_TAIL, table);
+
+    psFree(psEndTagName);
+
+    return;
+}
+
+psS32 psMetadataParseConfigXml(psMetadata** md, const char *fileName)
+{
+    psS32 status = 0;
+    FILE *fp = NULL;
+    xmlSAXHandler saxHandler;
+
+
+    // Error checks
+    PS_PTR_CHECK_NULL(fileName,-1);
+
+    // 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 -1;
+    }
+
+    // Parser and memory cleanups for libxml2
+    xmlCleanupParser();
+    xmlMemoryDump();
+
+    return 0;
+}
Index: /trunk/psLib/src/collections/psMetadata.c
===================================================================
--- /trunk/psLib/src/collections/psMetadata.c	(revision 2520)
+++ /trunk/psLib/src/collections/psMetadata.c	(revision 2521)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.37 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-11-09 00:36:13 $
+*  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-11-30 00:26:53 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -82,5 +82,6 @@
     psFree(metadataItem->items);
     if (type == PS_META_STR || type == PS_META_VEC || type == PS_META_IMG || type == PS_META_LOOKUPTABLE ||
-            type == PS_META_JPEG || type == PS_META_PNG || type == PS_META_ASTROM || type == PS_META_UNKNOWN) {
+            type == PS_META_JPEG || type == PS_META_PNG || type == PS_META_ASTROM || type == PS_META_UNKNOWN ||
+            type == PS_META_HASH) {
         psFree(metadataItem->data.V);
     }
@@ -183,4 +184,7 @@
     case PS_META_LOOKUPTABLE:
         metadataItem->data.V = va_arg(argPtr, psLookupTable*); // Deep copy of input data not performed
+        break;
+    case PS_META_HASH:
+        metadataItem->data.V = va_arg(argPtr, psHash*); // Deep copy of input data not performed
         break;
     case PS_META_IMG:
@@ -211,5 +215,4 @@
     // Allocate metadata's internal containers
     list = (psList* ) psListAlloc(NULL);
-
     table = (psHash* ) psHashAlloc(10);
 
Index: /trunk/psLib/src/collections/psMetadata.h
===================================================================
--- /trunk/psLib/src/collections/psMetadata.h	(revision 2520)
+++ /trunk/psLib/src/collections/psMetadata.h	(revision 2521)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-11-09 00:36:13 $
+*  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-11-30 00:27:14 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -40,4 +40,5 @@
     PS_META_STR,                       ///< String data (Stored in as psPtr ).
     PS_META_VEC,                       ///< Vector data (Stored in as psPtr ).
+    PS_META_HASH,                      ///< Hash data (Stored in as psPtr ).
     PS_META_IMG,                       ///< Image data (Stored in as psPtr ).
     PS_META_LOOKUPTABLE,               ///< Lookup table data (Stored as void *).
Index: /trunk/psLib/src/collections/psMetadataIO.c
===================================================================
--- /trunk/psLib/src/collections/psMetadataIO.c	(revision 2520)
+++ /trunk/psLib/src/collections/psMetadataIO.c	(revision 2521)
@@ -9,10 +9,11 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-11-10 18:26:46 $
+*  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-11-30 00:27:40 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */
 
+#include <libxml/parser.h>
 #include <fitsio.h>
 #include <string.h>
@@ -32,4 +33,10 @@
 #include "psAstronomyErrors.h"
 
+
+typedef struct
+{
+    int y;
+}
+myStruct;
 
 /******************************************************************************/
@@ -103,4 +110,8 @@
 /*****************************************************************************/
 
+void p_saxEndElement(void *ctx, const xmlChar *tagName);
+void p_psInitVectorXml(void *ctx, char *tagName);
+void p_psInitMetadataItemXml(void *ctx, char *tagName);
+void p_saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts);
 
 /** Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
@@ -329,7 +340,5 @@
         break;
     default:
-        psError(PS_ERR_BAD_PARAMETER_TYPE,true,
-                PS_ERRORTEXT_psMetadata_METATYPE_INVALID,
-                (int)type);
+        psError(PS_ERR_BAD_PARAMETER_TYPE,true, PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type);
     }
 }
@@ -680,2 +689,448 @@
     return failedLines;
 }
+
+void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts)
+{
+    psU64 i = 0;
+    psU64 lineNumber = 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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+
+    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
+    psTagName = psStringCopy(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_PTR_CHECK_NULL_GENERAL(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(attName);
+                psAttValue = psStringCopy(attValue);
+                psHashAdd(htAtts, psAttName, psAttValue);
+                psFree(psAttName);
+                psFree(psAttValue);
+            } else {
+                PS_PTR_CHECK_NULL_GENERAL(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, NULL, htAtts);
+
+    psFree(psTagName);
+
+    return;
+}
+
+void p_psInitMetadataItemXml(void *ctx, char *tagName)
+{
+    psBool overwrite = false;
+    psBool tempBool = false;
+    psS32 status = 0;
+    psU64 lineNumber = 0;
+    psF64 tempDbl = 0.0;
+    psS32 tempInt = 0.0;
+    psElemType elemType;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    metadataItem = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(metadataItem, return);
+    PS_PTR_CHECK_NULL_GENERAL(metadataItem->items, return);
+    psListSetIterator(metadataItem->items, PS_LIST_TAIL);
+    metadataItem = (psMetadataItem*)psListGetCurrent(metadataItem->items);
+    htAtts = (psHash*)metadataItem->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+    fileName = (char*)input->filename;
+    PS_PTR_CHECK_NULL_GENERAL(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;
+            elemType = PS_TYPE_PTR;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
+            mdType = PS_META_BOOL;
+            elemType = PS_TYPE_U8;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
+            mdType = PS_META_S32;
+            elemType = PS_TYPE_S32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
+            mdType = PS_META_F32;
+            elemType = PS_TYPE_F32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
+            mdType = PS_META_F64;
+            elemType = PS_TYPE_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_ITEM_SET) {
+                if(overwrite) {
+                    psMetadataRemove(md, PS_LIST_UNKNOWN, 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_ITEM_SET:
+        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
+        break;
+    case PS_META_BOOL:
+        tempBool = parseBool((char*)strValue, &status);
+        if(!status) {
+            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, 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, 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, NULL, tempDbl);
+        } else {
+            status = 0;
+            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
+                    lineNumber, fileName);
+        }
+        break;
+    case PS_META_STR:
+        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, strValue);
+        break;
+    default:
+        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineNumber, fileName);
+    } // End switch
+
+    return;
+}
+
+
+void p_psInitVectorXml(void *ctx, char *tagName)
+{
+    bool overwrite = false;
+    psS32 status = 0;
+    psU64 lineNumber = 0;
+    psElemType elemType;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    tables = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(tables, return);
+    PS_PTR_CHECK_NULL_GENERAL(tables->items, return);
+    psListSetIterator(tables->items, PS_LIST_TAIL);
+    table = (psMetadataItem*)psListGetCurrent(tables->items);
+    htAtts = (psHash*)table->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+    fileName = (char*)input->filename;
+    PS_PTR_CHECK_NULL_GENERAL(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;
+            elemType = PS_TYPE_PTR;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
+            mdType = PS_META_BOOL;
+            elemType = PS_TYPE_U8;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
+            mdType = PS_META_S32;
+            elemType = PS_TYPE_S32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
+            mdType = PS_META_F32;
+            elemType = PS_TYPE_F32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
+            mdType = PS_META_F64;
+            elemType = PS_TYPE_F64;
+        } else {
+            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strName, lineNumber,
+                    fileName);
+            return;
+        }
+    }
+
+    strValue = psHashLookup(htAtts, "value");
+    PS_PTR_CHECK_NULL_GENERAL(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_ITEM_SET) {
+                if(overwrite) {
+                    psMetadataRemove(md, PS_LIST_UNKNOWN, strName);
+                } else {
+                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
+                            fileName);
+                    return;
+                }
+            }
+        }
+    }
+
+    // Get value
+    vec = parseVector((char*)strValue, elemType, &status);
+    if(!status) {
+        psMetadataAdd(md, PS_LIST_TAIL, strName+1, mdType, NULL, vec);
+    } else {
+        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
+                lineNumber, fileName);
+    }
+    psFree(vec);
+}
+
+void saxEndElement(void *ctx, const xmlChar *tagName)
+{
+    psU64 lineNumber = 0;
+    char *psStartTagName = NULL;
+    char *psEndTagName = NULL;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    tables = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(tables, return);
+    PS_PTR_CHECK_NULL_GENERAL(tables->items, return);
+    psListSetIterator(tables->items, PS_LIST_TAIL);
+    table = (psMetadataItem*)psListGetCurrent(tables->items);
+    htAtts = (psHash*)table->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+
+    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
+    psEndTagName = psStringCopy(tagName);
+
+    // Compare start and end tag names
+    psStartTagName = psHashLookup(htAtts, "tagName");
+    PS_PTR_CHECK_NULL_GENERAL(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")) {
+        p_psInitMetadataItemXml(ctx, psEndTagName);
+    } else if(!strcmp(psEndTagName, "psVector")) {
+        p_psInitVectorXml(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->items, PS_LIST_TAIL, table);
+
+    psFree(psEndTagName);
+
+    return;
+}
+
+psS32 psMetadataParseConfigXml(psMetadata** md, const char *fileName)
+{
+    psS32 status = 0;
+    FILE *fp = NULL;
+    xmlSAXHandler saxHandler;
+
+
+    // Error checks
+    PS_PTR_CHECK_NULL(fileName,-1);
+
+    // 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 -1;
+    }
+
+    // Parser and memory cleanups for libxml2
+    xmlCleanupParser();
+    xmlMemoryDump();
+
+    return 0;
+}
Index: /trunk/psLib/src/types/psMetadata.c
===================================================================
--- /trunk/psLib/src/types/psMetadata.c	(revision 2520)
+++ /trunk/psLib/src/types/psMetadata.c	(revision 2521)
@@ -12,6 +12,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.37 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-11-09 00:36:13 $
+*  @version $Revision: 1.38 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-11-30 00:26:53 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -82,5 +82,6 @@
     psFree(metadataItem->items);
     if (type == PS_META_STR || type == PS_META_VEC || type == PS_META_IMG || type == PS_META_LOOKUPTABLE ||
-            type == PS_META_JPEG || type == PS_META_PNG || type == PS_META_ASTROM || type == PS_META_UNKNOWN) {
+            type == PS_META_JPEG || type == PS_META_PNG || type == PS_META_ASTROM || type == PS_META_UNKNOWN ||
+            type == PS_META_HASH) {
         psFree(metadataItem->data.V);
     }
@@ -183,4 +184,7 @@
     case PS_META_LOOKUPTABLE:
         metadataItem->data.V = va_arg(argPtr, psLookupTable*); // Deep copy of input data not performed
+        break;
+    case PS_META_HASH:
+        metadataItem->data.V = va_arg(argPtr, psHash*); // Deep copy of input data not performed
         break;
     case PS_META_IMG:
@@ -211,5 +215,4 @@
     // Allocate metadata's internal containers
     list = (psList* ) psListAlloc(NULL);
-
     table = (psHash* ) psHashAlloc(10);
 
Index: /trunk/psLib/src/types/psMetadata.h
===================================================================
--- /trunk/psLib/src/types/psMetadata.h	(revision 2520)
+++ /trunk/psLib/src/types/psMetadata.h	(revision 2521)
@@ -11,6 +11,6 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.25 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-11-09 00:36:13 $
+*  @version $Revision: 1.26 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-11-30 00:27:14 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -40,4 +40,5 @@
     PS_META_STR,                       ///< String data (Stored in as psPtr ).
     PS_META_VEC,                       ///< Vector data (Stored in as psPtr ).
+    PS_META_HASH,                      ///< Hash data (Stored in as psPtr ).
     PS_META_IMG,                       ///< Image data (Stored in as psPtr ).
     PS_META_LOOKUPTABLE,               ///< Lookup table data (Stored as void *).
Index: /trunk/psLib/src/types/psMetadataConfig.c
===================================================================
--- /trunk/psLib/src/types/psMetadataConfig.c	(revision 2520)
+++ /trunk/psLib/src/types/psMetadataConfig.c	(revision 2521)
@@ -9,10 +9,11 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-11-10 18:26:46 $
+*  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-11-30 00:27:40 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */
 
+#include <libxml/parser.h>
 #include <fitsio.h>
 #include <string.h>
@@ -32,4 +33,10 @@
 #include "psAstronomyErrors.h"
 
+
+typedef struct
+{
+    int y;
+}
+myStruct;
 
 /******************************************************************************/
@@ -103,4 +110,8 @@
 /*****************************************************************************/
 
+void p_saxEndElement(void *ctx, const xmlChar *tagName);
+void p_psInitVectorXml(void *ctx, char *tagName);
+void p_psInitMetadataItemXml(void *ctx, char *tagName);
+void p_saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts);
 
 /** Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
@@ -329,7 +340,5 @@
         break;
     default:
-        psError(PS_ERR_BAD_PARAMETER_TYPE,true,
-                PS_ERRORTEXT_psMetadata_METATYPE_INVALID,
-                (int)type);
+        psError(PS_ERR_BAD_PARAMETER_TYPE,true, PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type);
     }
 }
@@ -680,2 +689,448 @@
     return failedLines;
 }
+
+void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts)
+{
+    psU64 i = 0;
+    psU64 lineNumber = 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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+
+    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
+    psTagName = psStringCopy(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_PTR_CHECK_NULL_GENERAL(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(attName);
+                psAttValue = psStringCopy(attValue);
+                psHashAdd(htAtts, psAttName, psAttValue);
+                psFree(psAttName);
+                psFree(psAttValue);
+            } else {
+                PS_PTR_CHECK_NULL_GENERAL(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, NULL, htAtts);
+
+    psFree(psTagName);
+
+    return;
+}
+
+void p_psInitMetadataItemXml(void *ctx, char *tagName)
+{
+    psBool overwrite = false;
+    psBool tempBool = false;
+    psS32 status = 0;
+    psU64 lineNumber = 0;
+    psF64 tempDbl = 0.0;
+    psS32 tempInt = 0.0;
+    psElemType elemType;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    metadataItem = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(metadataItem, return);
+    PS_PTR_CHECK_NULL_GENERAL(metadataItem->items, return);
+    psListSetIterator(metadataItem->items, PS_LIST_TAIL);
+    metadataItem = (psMetadataItem*)psListGetCurrent(metadataItem->items);
+    htAtts = (psHash*)metadataItem->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+    fileName = (char*)input->filename;
+    PS_PTR_CHECK_NULL_GENERAL(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;
+            elemType = PS_TYPE_PTR;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
+            mdType = PS_META_BOOL;
+            elemType = PS_TYPE_U8;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
+            mdType = PS_META_S32;
+            elemType = PS_TYPE_S32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
+            mdType = PS_META_F32;
+            elemType = PS_TYPE_F32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
+            mdType = PS_META_F64;
+            elemType = PS_TYPE_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_ITEM_SET) {
+                if(overwrite) {
+                    psMetadataRemove(md, PS_LIST_UNKNOWN, 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_ITEM_SET:
+        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
+        break;
+    case PS_META_BOOL:
+        tempBool = parseBool((char*)strValue, &status);
+        if(!status) {
+            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, 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, 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, NULL, tempDbl);
+        } else {
+            status = 0;
+            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
+                    lineNumber, fileName);
+        }
+        break;
+    case PS_META_STR:
+        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, strValue);
+        break;
+    default:
+        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineNumber, fileName);
+    } // End switch
+
+    return;
+}
+
+
+void p_psInitVectorXml(void *ctx, char *tagName)
+{
+    bool overwrite = false;
+    psS32 status = 0;
+    psU64 lineNumber = 0;
+    psElemType elemType;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    tables = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(tables, return);
+    PS_PTR_CHECK_NULL_GENERAL(tables->items, return);
+    psListSetIterator(tables->items, PS_LIST_TAIL);
+    table = (psMetadataItem*)psListGetCurrent(tables->items);
+    htAtts = (psHash*)table->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+    fileName = (char*)input->filename;
+    PS_PTR_CHECK_NULL_GENERAL(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;
+            elemType = PS_TYPE_PTR;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
+            mdType = PS_META_BOOL;
+            elemType = PS_TYPE_U8;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
+            mdType = PS_META_S32;
+            elemType = PS_TYPE_S32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
+            mdType = PS_META_F32;
+            elemType = PS_TYPE_F32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
+            mdType = PS_META_F64;
+            elemType = PS_TYPE_F64;
+        } else {
+            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strName, lineNumber,
+                    fileName);
+            return;
+        }
+    }
+
+    strValue = psHashLookup(htAtts, "value");
+    PS_PTR_CHECK_NULL_GENERAL(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_ITEM_SET) {
+                if(overwrite) {
+                    psMetadataRemove(md, PS_LIST_UNKNOWN, strName);
+                } else {
+                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
+                            fileName);
+                    return;
+                }
+            }
+        }
+    }
+
+    // Get value
+    vec = parseVector((char*)strValue, elemType, &status);
+    if(!status) {
+        psMetadataAdd(md, PS_LIST_TAIL, strName+1, mdType, NULL, vec);
+    } else {
+        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
+                lineNumber, fileName);
+    }
+    psFree(vec);
+}
+
+void saxEndElement(void *ctx, const xmlChar *tagName)
+{
+    psU64 lineNumber = 0;
+    char *psStartTagName = NULL;
+    char *psEndTagName = NULL;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    tables = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(tables, return);
+    PS_PTR_CHECK_NULL_GENERAL(tables->items, return);
+    psListSetIterator(tables->items, PS_LIST_TAIL);
+    table = (psMetadataItem*)psListGetCurrent(tables->items);
+    htAtts = (psHash*)table->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+
+    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
+    psEndTagName = psStringCopy(tagName);
+
+    // Compare start and end tag names
+    psStartTagName = psHashLookup(htAtts, "tagName");
+    PS_PTR_CHECK_NULL_GENERAL(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")) {
+        p_psInitMetadataItemXml(ctx, psEndTagName);
+    } else if(!strcmp(psEndTagName, "psVector")) {
+        p_psInitVectorXml(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->items, PS_LIST_TAIL, table);
+
+    psFree(psEndTagName);
+
+    return;
+}
+
+psS32 psMetadataParseConfigXml(psMetadata** md, const char *fileName)
+{
+    psS32 status = 0;
+    FILE *fp = NULL;
+    xmlSAXHandler saxHandler;
+
+
+    // Error checks
+    PS_PTR_CHECK_NULL(fileName,-1);
+
+    // 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 -1;
+    }
+
+    // Parser and memory cleanups for libxml2
+    xmlCleanupParser();
+    xmlMemoryDump();
+
+    return 0;
+}
Index: /trunk/psLib/src/xml/psXML.c
===================================================================
--- /trunk/psLib/src/xml/psXML.c	(revision 2520)
+++ /trunk/psLib/src/xml/psXML.c	(revision 2521)
@@ -9,10 +9,11 @@
 *  @author Ross Harman, MHPCC
 *
-*  @version $Revision: 1.9 $ $Name: not supported by cvs2svn $
-*  @date $Date: 2004-11-10 18:26:46 $
+*  @version $Revision: 1.10 $ $Name: not supported by cvs2svn $
+*  @date $Date: 2004-11-30 00:27:40 $
 *
 *  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
 */
 
+#include <libxml/parser.h>
 #include <fitsio.h>
 #include <string.h>
@@ -32,4 +33,10 @@
 #include "psAstronomyErrors.h"
 
+
+typedef struct
+{
+    int y;
+}
+myStruct;
 
 /******************************************************************************/
@@ -103,4 +110,8 @@
 /*****************************************************************************/
 
+void p_saxEndElement(void *ctx, const xmlChar *tagName);
+void p_psInitVectorXml(void *ctx, char *tagName);
+void p_psInitMetadataItemXml(void *ctx, char *tagName);
+void p_saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts);
 
 /** Determines if a line is blank (whitespace only) or a commentline. It returns true if so. The input string
@@ -329,7 +340,5 @@
         break;
     default:
-        psError(PS_ERR_BAD_PARAMETER_TYPE,true,
-                PS_ERRORTEXT_psMetadata_METATYPE_INVALID,
-                (int)type);
+        psError(PS_ERR_BAD_PARAMETER_TYPE,true, PS_ERRORTEXT_psMetadata_METATYPE_INVALID, (int)type);
     }
 }
@@ -680,2 +689,448 @@
     return failedLines;
 }
+
+void saxStartElement(void *ctx, const xmlChar *tagName, const xmlChar **atts)
+{
+    psU64 i = 0;
+    psU64 lineNumber = 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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+
+    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
+    psTagName = psStringCopy(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_PTR_CHECK_NULL_GENERAL(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(attName);
+                psAttValue = psStringCopy(attValue);
+                psHashAdd(htAtts, psAttName, psAttValue);
+                psFree(psAttName);
+                psFree(psAttValue);
+            } else {
+                PS_PTR_CHECK_NULL_GENERAL(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, NULL, htAtts);
+
+    psFree(psTagName);
+
+    return;
+}
+
+void p_psInitMetadataItemXml(void *ctx, char *tagName)
+{
+    psBool overwrite = false;
+    psBool tempBool = false;
+    psS32 status = 0;
+    psU64 lineNumber = 0;
+    psF64 tempDbl = 0.0;
+    psS32 tempInt = 0.0;
+    psElemType elemType;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    metadataItem = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(metadataItem, return);
+    PS_PTR_CHECK_NULL_GENERAL(metadataItem->items, return);
+    psListSetIterator(metadataItem->items, PS_LIST_TAIL);
+    metadataItem = (psMetadataItem*)psListGetCurrent(metadataItem->items);
+    htAtts = (psHash*)metadataItem->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+    fileName = (char*)input->filename;
+    PS_PTR_CHECK_NULL_GENERAL(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;
+            elemType = PS_TYPE_PTR;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
+            mdType = PS_META_BOOL;
+            elemType = PS_TYPE_U8;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
+            mdType = PS_META_S32;
+            elemType = PS_TYPE_S32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
+            mdType = PS_META_F32;
+            elemType = PS_TYPE_F32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
+            mdType = PS_META_F64;
+            elemType = PS_TYPE_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_ITEM_SET) {
+                if(overwrite) {
+                    psMetadataRemove(md, PS_LIST_UNKNOWN, 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_ITEM_SET:
+        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, NULL);
+        break;
+    case PS_META_BOOL:
+        tempBool = parseBool((char*)strValue, &status);
+        if(!status) {
+            psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, 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, 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, NULL, tempDbl);
+        } else {
+            status = 0;
+            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
+                    lineNumber, fileName);
+        }
+        break;
+    case PS_META_STR:
+        psMetadataAdd(md, PS_LIST_TAIL, strName, mdType, NULL, strValue);
+        break;
+    default:
+        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_FILE_TYPE_INVALID, strType, lineNumber, fileName);
+    } // End switch
+
+    return;
+}
+
+
+void p_psInitVectorXml(void *ctx, char *tagName)
+{
+    bool overwrite = false;
+    psS32 status = 0;
+    psU64 lineNumber = 0;
+    psElemType elemType;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    tables = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(tables, return);
+    PS_PTR_CHECK_NULL_GENERAL(tables->items, return);
+    psListSetIterator(tables->items, PS_LIST_TAIL);
+    table = (psMetadataItem*)psListGetCurrent(tables->items);
+    htAtts = (psHash*)table->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+    fileName = (char*)input->filename;
+    PS_PTR_CHECK_NULL_GENERAL(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;
+            elemType = PS_TYPE_PTR;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psBool")) {
+            mdType = PS_META_BOOL;
+            elemType = PS_TYPE_U8;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psS32")) {
+            mdType = PS_META_S32;
+            elemType = PS_TYPE_S32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF32")) {
+            mdType = PS_META_F32;
+            elemType = PS_TYPE_F32;
+        } else if(xmlStrEqual(BAD_CAST strType, BAD_CAST "psF64")) {
+            mdType = PS_META_F64;
+            elemType = PS_TYPE_F64;
+        } else {
+            psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_TYPE_INVALID_LINE_FILE, strName, lineNumber,
+                    fileName);
+            return;
+        }
+    }
+
+    strValue = psHashLookup(htAtts, "value");
+    PS_PTR_CHECK_NULL_GENERAL(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_ITEM_SET) {
+                if(overwrite) {
+                    psMetadataRemove(md, PS_LIST_UNKNOWN, strName);
+                } else {
+                    psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_OVERWRITE_ITEM, strName, lineNumber,
+                            fileName);
+                    return;
+                }
+            }
+        }
+    }
+
+    // Get value
+    vec = parseVector((char*)strValue, elemType, &status);
+    if(!status) {
+        psMetadataAdd(md, PS_LIST_TAIL, strName+1, mdType, NULL, vec);
+    } else {
+        psError(PS_ERR_IO, true, PS_ERRORTEXT_psMetadataIO_PARSE_FAILED, strValue, strName, strType,
+                lineNumber, fileName);
+    }
+    psFree(vec);
+}
+
+void saxEndElement(void *ctx, const xmlChar *tagName)
+{
+    psU64 lineNumber = 0;
+    char *psStartTagName = NULL;
+    char *psEndTagName = NULL;
+    psMetadataType mdType;
+    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_PTR_CHECK_NULL_GENERAL(ctxt, return);
+    md = (psMetadata*)ctxt->sax->_private;
+    PS_PTR_CHECK_NULL_GENERAL(md, return);
+    input = (xmlParserInputPtr)ctxt->input;
+    PS_PTR_CHECK_NULL_GENERAL(input, return);
+    tables = psMetadataLookup(md, "htAtts");
+    PS_PTR_CHECK_NULL_GENERAL(tables, return);
+    PS_PTR_CHECK_NULL_GENERAL(tables->items, return);
+    psListSetIterator(tables->items, PS_LIST_TAIL);
+    table = (psMetadataItem*)psListGetCurrent(tables->items);
+    htAtts = (psHash*)table->data.V;
+    PS_PTR_CHECK_NULL_GENERAL(htAtts, return);
+
+    // Copy XML strings to psStrings to avoid libxml2/psLib memory corruption problems
+    psEndTagName = psStringCopy(tagName);
+
+    // Compare start and end tag names
+    psStartTagName = psHashLookup(htAtts, "tagName");
+    PS_PTR_CHECK_NULL_GENERAL(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")) {
+        p_psInitMetadataItemXml(ctx, psEndTagName);
+    } else if(!strcmp(psEndTagName, "psVector")) {
+        p_psInitVectorXml(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->items, PS_LIST_TAIL, table);
+
+    psFree(psEndTagName);
+
+    return;
+}
+
+psS32 psMetadataParseConfigXml(psMetadata** md, const char *fileName)
+{
+    psS32 status = 0;
+    FILE *fp = NULL;
+    xmlSAXHandler saxHandler;
+
+
+    // Error checks
+    PS_PTR_CHECK_NULL(fileName,-1);
+
+    // 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 -1;
+    }
+
+    // Parser and memory cleanups for libxml2
+    xmlCleanupParser();
+    xmlMemoryDump();
+
+    return 0;
+}
Index: /trunk/psLib/test/astronomy/Makefile
===================================================================
--- /trunk/psLib/test/astronomy/Makefile	(revision 2520)
+++ /trunk/psLib/test/astronomy/Makefile	(revision 2521)
@@ -3,6 +3,6 @@
 ##  Makefile:   test/astronomy
 ##
-##  $Revision: 1.22 $  $Name: not supported by cvs2svn $
-##  $Date: 2004-11-09 01:10:15 $
+##  $Revision: 1.23 $  $Name: not supported by cvs2svn $
+##  $Date: 2004-11-30 00:28:36 $
 ##
 ##  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
@@ -16,6 +16,6 @@
 include ../../src/Makefile.Globals
 
-CFLAGS := -I../../include $(CFLAGS)
-LDFLAGS := -L../../lib -lpslib -lpstest $(LDFLAGS)
+CFLAGS := -I../../include -I/usr/include/libxml $(CFLAGS)
+LDFLAGS := -L../../lib -lpslib -lpstest -lxml2 $(LDFLAGS)
 
 TARGET = tst_psTime_01 \
@@ -30,4 +30,5 @@
          tst_psMetadata_05 \
          tst_psMetadata_06 \
+         tst_psMetadata_07 \
          tst_psCoord \
          tst_psAstrometry \
Index: /trunk/psLib/test/astronomy/tst_psMetadata_07.c
===================================================================
--- /trunk/psLib/test/astronomy/tst_psMetadata_07.c	(revision 2521)
+++ /trunk/psLib/test/astronomy/tst_psMetadata_07.c	(revision 2521)
@@ -0,0 +1,45 @@
+/** @file  tst_psMetadata_07.c
+*
+*  @brief Test driver for psMetadataIO functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Read an XML config file
+*     Test B - Free data
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-11-30 00:29:06 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+#include "pslib.h"
+#include "psTest.h"
+
+
+int main(int argc, char* argv[])
+{
+    // Test A - Read an XML config file
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Read an XML config file");
+    int res = 0;
+    psMetadata *md = NULL;
+    res = psMetadataParseConfigXml(&md, "../../config/psTime.xml");
+    if (res != 0) {
+        printf("psMetadataParseConfigXml returned error %d\n", res);
+    }
+    psFree(md);
+    printFooter(stdout, "psMetadata", "Test A - Read an XML config file", true);
+
+
+    // Test B - Free data
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Free data");
+    psMemCheckLeaks(0, NULL, stdout);
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test B - Free data", true);
+
+    return 0;
+}
Index: /trunk/psLib/test/collections/tst_psMetadata_07.c
===================================================================
--- /trunk/psLib/test/collections/tst_psMetadata_07.c	(revision 2521)
+++ /trunk/psLib/test/collections/tst_psMetadata_07.c	(revision 2521)
@@ -0,0 +1,45 @@
+/** @file  tst_psMetadata_07.c
+*
+*  @brief Test driver for psMetadataIO functions
+*
+*  This test driver contains the following tests for psMetadata:
+*     Test A - Read an XML config file
+*     Test B - Free data
+*
+*  @author  Ross Harman, MHPCC
+*
+*  @version $Revision: 1.1 $  $Name: not supported by cvs2svn $
+*  @date  $Date: 2004-11-30 00:29:06 $
+*
+*  Copyright 2004 Maui High Performance Computing Center, University of Hawaii
+*
+*/
+#include "pslib.h"
+#include "psTest.h"
+
+
+int main(int argc, char* argv[])
+{
+    // Test A - Read an XML config file
+    printPositiveTestHeader(stdout, "psMetadata", "Test A - Read an XML config file");
+    int res = 0;
+    psMetadata *md = NULL;
+    res = psMetadataParseConfigXml(&md, "../../config/psTime.xml");
+    if (res != 0) {
+        printf("psMetadataParseConfigXml returned error %d\n", res);
+    }
+    psFree(md);
+    printFooter(stdout, "psMetadata", "Test A - Read an XML config file", true);
+
+
+    // Test B - Free data
+    printPositiveTestHeader(stdout, "psMetadata", "Test B - Free data");
+    psMemCheckLeaks(0, NULL, stdout);
+    psS32 nBad = psMemCheckCorruption(0);
+    if(nBad) {
+        printf("ERROR: Found %d bad memory blocks\n", nBad);
+    }
+    printFooter(stdout, "psMetadata", "Test B - Free data", true);
+
+    return 0;
+}
