From 24a300ffa4aad25811ac0d5be6dc7408fd720910 Mon Sep 17 00:00:00 2001
From: Draekko <draekko.software+exiv2@gmail.com>
Date: Sat, 24 Jun 2017 10:18:33 -0400
Subject: [PATCH] New branch for split XMP SDK and C++11 changes

---
 CMakeLists.txt                                   |   89 +-
 Makefile                                         |    8 +-
 README-CMAKE                                     |    1 -
 config/CMakeChecks.txt                           |    8 +-
 config/Makefile.in                               |    8 +-
 config/aclocal.m4                                |  982 ++++++++++
 config/config.mk.in                              |   16 +-
 config/configure.ac                              |   37 +-
 contrib/cmake/msvc/ReadMe.txt                    |    1 -
 contrib/organize/helpers.cpp                     |    2 +-
 include/exiv2/basicio.hpp                        |    5 +-
 include/exiv2/datasets.hpp                       |    4 +
 include/exiv2/exiv2.hpp                          |    2 +-
 include/exiv2/image.hpp                          |    6 +-
 include/exiv2/metadatum.hpp                      |    4 +
 include/exiv2/properties.hpp                     |    4 +
 include/exiv2/tags.hpp                           |    4 +
 include/exiv2/value.hpp                          |   52 +
 include/exiv2/{xmp.hpp => xmp_exiv2.hpp}         |   10 +-
 samples/CMakeLists.txt                           |   11 +-
 samples/Makefile                                 |    2 +-
 samples/metacopy.cpp                             |    4 +
 src/CMakeLists.txt                               |   47 +-
 {xmpsdk/src => src}/MD5.cpp                      |   25 +-
 {xmpsdk/include => src}/MD5.h                    |    8 +-
 src/Makefile                                     |    9 +-
 src/actions.cpp                                  |   14 +-
 src/actions.hpp                                  |   40 +
 src/asfvideo.cpp                                 |   11 +
 src/bmpimage.cpp                                 |   11 +
 src/convert.cpp                                  |   16 +-
 src/cr2image.cpp                                 |   13 +
 src/crwimage.cpp                                 |   25 +
 src/crwimage_int.hpp                             |    8 +
 src/epsimage.cpp                                 |    9 +
 src/exif.cpp                                     |   29 +
 src/exiv2.cpp                                    |    2 +-
 src/gifimage.cpp                                 |    9 +
 src/image.cpp                                    |   38 +
 src/iptc.cpp                                     |    8 +
 src/jp2image.cpp                                 |    9 +
 src/jpgimage.cpp                                 |   24 +
 src/matroskavideo.cpp                            |    9 +
 src/mrwimage.cpp                                 |    9 +
 src/orfimage.cpp                                 |   13 +
 src/pgfimage.cpp                                 |   10 +
 src/pngchunk.cpp                                 |    5 +
 src/pngimage.cpp                                 |    9 +
 src/preview.cpp                                  |    4 +
 src/properties.cpp                               |    4 +-
 src/psdimage.cpp                                 |    9 +
 src/quicktimevideo.cpp                           |   10 +
 src/rafimage.cpp                                 |    9 +
 src/riffvideo.cpp                                |    9 +
 src/rw2image.cpp                                 |    9 +
 src/tgaimage.cpp                                 |    9 +
 src/tiffcomposite.cpp                            |   84 +
 src/tiffcomposite_int.hpp                        |   11 +
 src/tifffwd_int.hpp                              |    4 +
 src/tiffimage.cpp                                |   30 +
 src/tiffimage_int.hpp                            |   14 +
 src/tiffvisitor.cpp                              |   28 +
 src/version.cpp                                  |    2 +-
 src/webpimage.cpp                                |    9 +
 src/{xmp.cpp => xmp_exiv2.cpp}                   |   68 +-
 src/xmpsidecar.cpp                               |   11 +-
 xmpsdk/CMakeLists.txt                            |   44 -
 xmpsdk/Readme.txt                                |   42 +
 xmpsdk/include/TXMPIterator.hpp                  |  235 ---
 xmpsdk/include/TXMPMeta.hpp                      | 1803 ------------------
 xmpsdk/include/TXMPUtils.hpp                     |  965 ----------
 xmpsdk/include/XMP.incl_cpp                      |   63 -
 xmpsdk/include/XMPSDK.hpp                        |   89 -
 xmpsdk/include/XMP_Const.h                       | 1330 --------------
 xmpsdk/include/XMP_Environment.h                 |  164 --
 xmpsdk/include/XMP_Version.h                     |   45 -
 xmpsdk/include/client-glue/TXMPIterator.incl_cpp |  226 ---
 xmpsdk/include/client-glue/TXMPMeta.incl_cpp     |  935 ----------
 xmpsdk/include/client-glue/TXMPUtils.incl_cpp    |  493 -----
 xmpsdk/include/client-glue/WXMPFiles.hpp         |  167 --
 xmpsdk/include/client-glue/WXMPIterator.hpp      |   83 -
 xmpsdk/include/client-glue/WXMPMeta.hpp          |  622 -------
 xmpsdk/include/client-glue/WXMPUtils.hpp         |  322 ----
 xmpsdk/include/client-glue/WXMP_Common.hpp       |  123 --
 xmpsdk/ren-lnx.sh                                |    4 +
 xmpsdk/ren-mac.sh                                |    4 +
 xmpsdk/ren-win.bat                               |    2 +
 xmpsdk/src/ExpatAdapter.cpp                      |  504 -----
 xmpsdk/src/ExpatAdapter.hpp                      |   50 -
 xmpsdk/src/Makefile                              |  153 --
 xmpsdk/src/ParseRDF.cpp                          | 1296 -------------
 xmpsdk/src/UnicodeConversions.cpp                | 1665 -----------------
 xmpsdk/src/UnicodeConversions.hpp                |  121 --
 xmpsdk/src/UnicodeInlines.incl_cpp               |  129 --
 xmpsdk/src/WXMPIterator.cpp                      |  188 --
 xmpsdk/src/WXMPMeta.cpp                          | 1310 -------------
 xmpsdk/src/WXMPUtils.cpp                         |  626 -------
 xmpsdk/src/XMLParserAdapter.hpp                  |  140 --
 xmpsdk/src/XML_Node.cpp                          |  463 -----
 xmpsdk/src/XMPCore_Impl.cpp                      | 1468 ---------------
 xmpsdk/src/XMPCore_Impl.hpp                      |  534 ------
 xmpsdk/src/XMPIterator.cpp                       |  736 --------
 xmpsdk/src/XMPIterator.hpp                       |  148 --
 xmpsdk/src/XMPMeta-GetSet.cpp                    | 1212 ------------
 xmpsdk/src/XMPMeta-Parse.cpp                     | 1291 -------------
 xmpsdk/src/XMPMeta-Serialize.cpp                 | 1342 --------------
 xmpsdk/src/XMPMeta.cpp                           | 1649 -----------------
 xmpsdk/src/XMPMeta.hpp                           |  418 -----
 xmpsdk/src/XMPUtils-FileInfo.cpp                 | 1346 --------------
 xmpsdk/src/XMPUtils.cpp                          | 2135 ----------------------
 xmpsdk/src/XMPUtils.hpp                          |  221 ---
 xmpsdk/src/XMP_BuildInfo.h                       |   22 -
 112 files changed, 1880 insertions(+), 27042 deletions(-)
 rename include/exiv2/{xmp.hpp => xmp_exiv2.hpp} (98%)
 rename {xmpsdk/src => src}/MD5.cpp (92%)
 rename {xmpsdk/include => src}/MD5.h (83%)
 rename src/{xmp.cpp => xmp_exiv2.cpp} (94%)
 delete mode 100644 xmpsdk/CMakeLists.txt
 create mode 100644 xmpsdk/Readme.txt
 delete mode 100644 xmpsdk/include/TXMPIterator.hpp
 delete mode 100644 xmpsdk/include/TXMPMeta.hpp
 delete mode 100644 xmpsdk/include/TXMPUtils.hpp
 delete mode 100644 xmpsdk/include/XMP.incl_cpp
 delete mode 100644 xmpsdk/include/XMPSDK.hpp
 delete mode 100644 xmpsdk/include/XMP_Const.h
 delete mode 100644 xmpsdk/include/XMP_Environment.h
 delete mode 100644 xmpsdk/include/XMP_Version.h
 delete mode 100644 xmpsdk/include/client-glue/TXMPIterator.incl_cpp
 delete mode 100644 xmpsdk/include/client-glue/TXMPMeta.incl_cpp
 delete mode 100644 xmpsdk/include/client-glue/TXMPUtils.incl_cpp
 delete mode 100644 xmpsdk/include/client-glue/WXMPFiles.hpp
 delete mode 100644 xmpsdk/include/client-glue/WXMPIterator.hpp
 delete mode 100644 xmpsdk/include/client-glue/WXMPMeta.hpp
 delete mode 100644 xmpsdk/include/client-glue/WXMPUtils.hpp
 delete mode 100644 xmpsdk/include/client-glue/WXMP_Common.hpp
 create mode 100755 xmpsdk/ren-lnx.sh
 create mode 100755 xmpsdk/ren-mac.sh
 create mode 100644 xmpsdk/ren-win.bat
 delete mode 100644 xmpsdk/src/ExpatAdapter.cpp
 delete mode 100644 xmpsdk/src/ExpatAdapter.hpp
 delete mode 100644 xmpsdk/src/Makefile
 delete mode 100644 xmpsdk/src/ParseRDF.cpp
 delete mode 100644 xmpsdk/src/UnicodeConversions.cpp
 delete mode 100644 xmpsdk/src/UnicodeConversions.hpp
 delete mode 100644 xmpsdk/src/UnicodeInlines.incl_cpp
 delete mode 100644 xmpsdk/src/WXMPIterator.cpp
 delete mode 100644 xmpsdk/src/WXMPMeta.cpp
 delete mode 100644 xmpsdk/src/WXMPUtils.cpp
 delete mode 100644 xmpsdk/src/XMLParserAdapter.hpp
 delete mode 100644 xmpsdk/src/XML_Node.cpp
 delete mode 100644 xmpsdk/src/XMPCore_Impl.cpp
 delete mode 100644 xmpsdk/src/XMPCore_Impl.hpp
 delete mode 100644 xmpsdk/src/XMPIterator.cpp
 delete mode 100644 xmpsdk/src/XMPIterator.hpp
 delete mode 100644 xmpsdk/src/XMPMeta-GetSet.cpp
 delete mode 100644 xmpsdk/src/XMPMeta-Parse.cpp
 delete mode 100644 xmpsdk/src/XMPMeta-Serialize.cpp
 delete mode 100644 xmpsdk/src/XMPMeta.cpp
 delete mode 100644 xmpsdk/src/XMPMeta.hpp
 delete mode 100644 xmpsdk/src/XMPUtils-FileInfo.cpp
 delete mode 100644 xmpsdk/src/XMPUtils.cpp
 delete mode 100644 xmpsdk/src/XMPUtils.hpp
 delete mode 100644 xmpsdk/src/XMP_BuildInfo.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 130cb56e..8c19d590 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,6 +17,13 @@ if( EXISTS "${CMAKE_SOURCE_DIR}/include/exiv2/exv_conf.h"  )
 endif()
 ##
 
+if( EXISTS "${CMAKE_SOURCE_DIR}/xmpsdk/include"  )
+    set( ADOBE_XMP_SDK_INCLUDE ON )
+else()
+    set( ADOBE_XMP_SDK_INCLUDE OFF )
+    message( FATAL_ERROR "Missing Adobe XMP SDK include files. Setup cannot proceed." )
+endif()
+
 CMAKE_MINIMUM_REQUIRED( VERSION 3.1.0 )
 PROJECT( exiv2 )
 
@@ -38,9 +45,12 @@ SET( GENERIC_LIB_VERSION    "26.0.0" )
 SET( GENERIC_LIB_SOVERSION  "26" )
 
 # options and their default values
+OPTION( EXIV2_CPP_STANDARD           "Set the C++ Standard to compile with"                 11  )
+OPTION( EXIV2_CPP_STANDARD_REQUIRED  "Set C++ Standard to required"                         ON  )
+OPTION( EXIV2_CPP_EXTENSION          "Set C++ Extensions to required"                       OFF )
+OPTION( EXIV2_ENABLE_VERBOSITY       "Enable verbosity"                                     OFF )
 OPTION( EXIV2_ENABLE_SHARED        "Build exiv2 as a shared library (dll)"                 ON  )
 OPTION( EXIV2_ENABLE_XMP           "Build with XMP metadata support"                       ON  )
-OPTION( EXIV2_ENABLE_LIBXMP        "Build a static convenience Library for XMP"            ON  )
 OPTION( EXIV2_ENABLE_PNG           "Build with png support (requires libz)"                ON  )
 OPTION( EXIV2_ENABLE_NLS           "Build native language support (requires gettext)"      ON  )
 OPTION( EXIV2_ENABLE_PRINTUCS2     "Build with Printucs2"                                  ON  )
@@ -61,9 +71,28 @@ ELSE()
     SET ( EXIV2_ENABLE_DYNAMIC_RUNTIME OFF )
 ENDIF()
 
+SET ( CMAKE_VERBOSE_MAKEFILE ${EXIV2_ENABLE_VERBOSITY} )
+IF ( NOT ${EXIV2_CPP_STANDARD} )
+    SET ( EXIV2_CPP_STANDARD 11 )
+ENDIF ()
+
 # set include path for FindXXX.cmake files
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/config/")
 
+IF ( WIN32 OR MINGW OR MSVC )
+    SET( XMPLIB_EXT lib )
+ELSE()
+    SET( XMPLIB_EXT a )
+ENDIF()
+
+IF ( EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/libXMPCore.${XMPLIB_EXT}" AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/libXMPFiles.${XMPLIB_EXT}" )
+    MESSAGE( STATUS "Has xmp sdk library files" )
+    SET ( EXV_HAS_XMP_SDK_LIBS ON )
+ELSE()
+    MESSAGE( STATUS "Doesn't have xmp sdk library files" )
+    SET ( EXV_HAS_XMP_SDK_LIBS OFF )
+ENDIF()
+
 IF( MINGW OR UNIX )
     IF ( CMAKE_CXX_COMPILER STREQUAL "g++" OR CMAKE_C_COMPILER STREQUAL "gcc" )
         ADD_DEFINITIONS(-Wall
@@ -87,14 +116,16 @@ IF( MINGW OR UNIX )
 
     message(STATUS Compiler: ${COMPILER} " Major:" ${GCC_MAJOR} " Minor:" ${GCC_MINOR})
 
-    IF ( CYGWIN OR ( ${GCC_MAJOR} GREATER 5 ))
-        ADD_DEFINITIONS( -std=gnu++98 ) # to support snprintf
-    ELSE()
-        ADD_DEFINITIONS( -std=c++98 )
-    ENDIF()
-
 ENDIF( MINGW OR UNIX )
 
+set( CMAKE_CXX_STANDARD ${EXIV2_CPP_STANDARD} )
+set( CMAKE_CXX_STANDARD_REQUIRED ${EXIV2_CPP_STANDARD_REQUIRED} )
+set( CMAKE_CXX_EXTENSIONS ${EXIV2_CPP_EXTENSION} )
+
+IF ( ${EXIV2_CPP_STANDARD} LESS 98 AND ${EXIV2_CPP_STANDARD} GREATER 10  )
+    ADD_DEFINITIONS( -DEXV_USING_CPP_ELEVEN=1  )
+ENDIF()
+
 IF( EXIV2_ENABLE_COMMERCIAL )
     SET (EXIV2_ENABLE_LENSDATA OFF)
     SET (EXIV2_ENABLE_NLS OFF)
@@ -130,38 +161,40 @@ SET( INSTALL_TARGET_STANDARD_ARGS
      ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
 )
 
-##
-# add sources from XMPSDK directory
-# this needs to be done here to be visible to xmpsdk, src and sample sub directories
-SET( XMPSRC ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/ExpatAdapter.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/MD5.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/ParseRDF.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/UnicodeConversions.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/WXMPIterator.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/WXMPMeta.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/WXMPUtils.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/XML_Node.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/XMPCore_Impl.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/XMPIterator.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/XMPMeta-GetSet.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/XMPMeta-Parse.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/XMPMeta-Serialize.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/XMPMeta.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/XMPUtils-FileInfo.cpp
-            ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/src/XMPUtils.cpp
+IF ( WIN32 OR MINGW OR MSVC )
+    SET( XMPLIB_EXT lib )
+ELSE()
+    SET( XMPLIB_EXT a )
+ENDIF()
+
+IF ( EXV_HAS_XMP_SDK_LIBS )
+    SET ( XMPLIBS ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/libXMPCore.${XMPLIB_EXT}
+                  ${CMAKE_CURRENT_SOURCE_DIR}/xmpsdk/libXMPFiles.${XMPLIB_EXT}
 )
+ENDIF()
+
+##
+# Adobe XMP SDK definitions
+IF( MSVC OR WIN32 OR MINGW)
+  ADD_DEFINITIONS( -DXMP_WinBuild=1 -DWIN_ENV=1 )
+ELSEIF( UNIX AND APPLE) 
+  ADD_DEFINITIONS( -DXMP_MacBuild=1 -DMAC_ENV=1 )
+ELSE()
+  ADD_DEFINITIONS( -DXMP_UNIXBuild=1 -DUNIX_ENV=1 )
+ENDIF()
 
 # the following lines need to be added to circumvent the error in xmpsdk\src\MD5.h
 IF( ${EXV_HAVE_STDINT_H} )
     ADD_DEFINITIONS( -DEXV_HAVE_STDINT_H )
 ENDIF( ${EXV_HAVE_STDINT_H} )
 
-ADD_SUBDIRECTORY( xmpsdk )
 ADD_SUBDIRECTORY( src )
 
+IF ( EXV_HAS_XMP_SDK_LIBS )
 IF( EXIV2_ENABLE_BUILD_SAMPLES )
     ADD_SUBDIRECTORY( samples )
 ENDIF( EXIV2_ENABLE_BUILD_SAMPLES )
+ENDIF()
 
 IF( EXIV2_ENABLE_BUILD_PO )
     ADD_SUBDIRECTORY( po )
@@ -169,8 +202,10 @@ ENDIF( EXIV2_ENABLE_BUILD_PO )
 
 ##
 # tests
+IF ( EXV_HAS_XMP_SDK_LIBS )
 ADD_CUSTOM_TARGET(tests       COMMAND env EXIV2_BINDIR="${CMAKE_BINARY_DIR}"/bin make tests       WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" )
 ADD_CUSTOM_TARGET(geotag-test COMMAND env EXIV2_BINDIR="${CMAKE_BINARY_DIR}"/bin make geotag-test WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" )
+ENDIF()
 
 ##
 # http://dev.exiv2.org/boards/3/topics/1364
diff --git a/Makefile b/Makefile
index efca81b1..7b1a78f2 100644
--- a/Makefile
+++ b/Makefile
@@ -52,11 +52,11 @@
 SHELL = /bin/sh
 ENABLE_XMP = 1
 
-.PHONY: all doc config samples xmpsdk                \
+.PHONY: all doc config samples                 \
         mostlyclean clean distclean maintainer-clean \
         install uninstall tests teste testv
 
-all install: config/config.mk xmpsdk
+all install: config/config.mk
 	cd src && $(MAKE) $(MAKECMDGOALS)
 	cd po && $(MAKE) $(MAKECMDGOALS)
 
@@ -133,15 +133,11 @@ configure:
 config:
 	cd config && $(MAKE) -f config.make $(MAKECMDGOALS)
 
-xmpsdk: config/config.mk
-	if test "x$(ENABLE_XMP)" = "x1"; then cd xmpsdk/src && $(MAKE) $@; fi;
-
 mostlyclean clean: config/config.mk
 	cd src && $(MAKE) $(MAKECMDGOALS)
 	cd doc && $(MAKE) $(MAKECMDGOALS)
 	cd samples && $(MAKE) $(MAKECMDGOALS)
 	cd test && $(MAKE) $(MAKECMDGOALS)
-	cd xmpsdk/src && $(MAKE) $(MAKECMDGOALS)
 	cd config && $(MAKE) -f config.make $(MAKECMDGOALS)
 	cd po && $(MAKE) $(MAKECMDGOALS)
 	rm -f include/exiv2/exv_conf.h
diff --git a/README-CMAKE b/README-CMAKE
index 438f87cb..7e184248 100644
--- a/README-CMAKE
+++ b/README-CMAKE
@@ -88,7 +88,6 @@ Specific Exiv2 options :
 
 -DEXIV2_ENABLE_SHARED        : Build exiv2 as a shared library (dll).            [default=on ]
 -DEXIV2_ENABLE_XMP           : Build with XMP metadata support.                  [default=on ]
--DEXIV2_ENABLE_LIBXMP        : Build a static convenience Library for XMP.       [default=on ]
 -DEXIV2_ENABLE_PNG           : Build with png support (requires libz).           [default=on ]
 -DEXIV2_ENABLE_NLS           : Build native language support (requires gettext). [default=on ]
 -DEXIV2_ENABLE_PRINTUCS2     : Build with Printucs2.                             [default=on ]
diff --git a/config/CMakeChecks.txt b/config/CMakeChecks.txt
index ded0f546..5d8b82a6 100644
--- a/config/CMakeChecks.txt
+++ b/config/CMakeChecks.txt
@@ -78,6 +78,8 @@ IF( EXIV2_ENABLE_WEBREADY )
     ENDIF( EXIV2_ENABLE_SSH )
 ENDIF( EXIV2_ENABLE_WEBREADY )
 
+
+IF ( EXV_HAS_XMP_SDK_LIBS )
 IF (EXIV2_ENABLE_XMP)
     FIND_PACKAGE(EXPAT REQUIRED)
     INCLUDE_DIRECTORIES(${EXPAT_INCLUDE_DIR})
@@ -88,6 +90,7 @@ IF (EXIV2_ENABLE_XMP)
         ENDIF( NOT EXPAT_FOUND )
     ENDIF( MINGW OR UNIX )
 ENDIF (EXIV2_ENABLE_XMP)
+ENDIF ()
 
 IF( EXIV2_ENABLE_SHARED )
     ADD_DEFINITIONS( -DEXV_HAVE_DLL )
@@ -326,10 +329,13 @@ ENDMACRO( OptionOutput _outputstring )
 
 MESSAGE( STATUS "------------------------------------------------------------------" )
 MESSAGE( STATUS "${PACKAGE_STRING} configure results        <${PACKAGE_URL}>"        )
+MESSAGE( STATUS "C++ standard                        ${EXIV2_CPP_STANDARD}"          )
+OptionOutput( "C++ standard required               " EXIV2_CPP_STANDARD_REQUIRED     )
+OptionOutput( "C++ extensions required             " EXIV2_CPP_EXTENSION             )
+OptionOutput( "Enabled compilation verbosity       " EXIV2_ENABLE_VERBOSITY          )
 OptionOutput( "Building PNG support:               " EXIV2_ENABLE_PNG AND ZLIB_FOUND )
 OptionOutput( "Building shared library:            " EXIV2_ENABLE_SHARED             )
 OptionOutput( "XMP metadata support:               " EXIV2_ENABLE_XMP                )
-OptionOutput( "Building static libxmp:             " EXIV2_ENABLE_LIBXMP             )
 OptionOutput( "Native language support:            " EXIV2_ENABLE_NLS                )
 OptionOutput( "Conversion of Windows XP tags:      " EXIV2_ENABLE_PRINTUCS2          )
 OptionOutput( "Nikon lens database:                " EXIV2_ENABLE_LENSDATA           )
diff --git a/config/Makefile.in b/config/Makefile.in
index efca81b1..7b1a78f2 100644
--- a/config/Makefile.in
+++ b/config/Makefile.in
@@ -52,11 +52,11 @@
 SHELL = /bin/sh
 ENABLE_XMP = 1
 
-.PHONY: all doc config samples xmpsdk                \
+.PHONY: all doc config samples                 \
         mostlyclean clean distclean maintainer-clean \
         install uninstall tests teste testv
 
-all install: config/config.mk xmpsdk
+all install: config/config.mk
 	cd src && $(MAKE) $(MAKECMDGOALS)
 	cd po && $(MAKE) $(MAKECMDGOALS)
 
@@ -133,15 +133,11 @@ configure:
 config:
 	cd config && $(MAKE) -f config.make $(MAKECMDGOALS)
 
-xmpsdk: config/config.mk
-	if test "x$(ENABLE_XMP)" = "x1"; then cd xmpsdk/src && $(MAKE) $@; fi;
-
 mostlyclean clean: config/config.mk
 	cd src && $(MAKE) $(MAKECMDGOALS)
 	cd doc && $(MAKE) $(MAKECMDGOALS)
 	cd samples && $(MAKE) $(MAKECMDGOALS)
 	cd test && $(MAKE) $(MAKECMDGOALS)
-	cd xmpsdk/src && $(MAKE) $(MAKECMDGOALS)
 	cd config && $(MAKE) -f config.make $(MAKECMDGOALS)
 	cd po && $(MAKE) $(MAKECMDGOALS)
 	rm -f include/exiv2/exv_conf.h
diff --git a/config/aclocal.m4 b/config/aclocal.m4
index 3af6a50b..0c2beac0 100644
--- a/config/aclocal.m4
+++ b/config/aclocal.m4
@@ -10198,3 +10198,985 @@ AC_DEFUN([AX_CXX_CHECK_FLAG],[
     $5
   ])
 ])
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the specified
+#   version of the C++ standard.  If necessary, add switches to CXX and
+#   CXXCPP to enable support.  VERSION may be '11' (for the C++11 standard)
+#   or '14' (for the C++14 standard).
+#
+#   The second argument, if specified, indicates whether you insist on an
+#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+#   -std=c++11).  If neither is specified, you get whatever works, with
+#   preference for an extended mode.
+#
+#   The third argument, if specified 'mandatory' or if left unspecified,
+#   indicates that baseline support for the specified C++ standard is
+#   required and that the macro should error out if no mode with that
+#   support is found.  If specified 'optional', then configuration proceeds
+#   regardless, after defining HAVE_CXX${VERSION} if and only if a
+#   supporting mode is found.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+#   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
+#   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
+#   Copyright (c) 2015 Paul Norman <penorman@mac.com>
+#   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
+#   Copyright (c) 2016 Krzesimir Nowak <qdlacz@gmail.com>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.  This file is offered as-is, without any
+#   warranty.
+
+#serial 6
+
+dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
+dnl  (serial version number 13).
+
+AX_REQUIRE_DEFINED([AC_MSG_WARN])
+AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
+  m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
+        [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
+        [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
+        [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$2], [], [],
+        [$2], [ext], [],
+        [$2], [noext], [],
+        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
+        [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
+  AC_LANG_PUSH([C++])dnl
+  ac_success=no
+  AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
+  ax_cv_cxx_compile_cxx$1,
+  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+    [ax_cv_cxx_compile_cxx$1=yes],
+    [ax_cv_cxx_compile_cxx$1=no])])
+  if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
+    ac_success=yes
+  fi
+
+  m4_if([$2], [noext], [], [dnl
+  if test x$ac_success = xno; then
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      switch="-std=gnu++${alternative}"
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                     $cachevar,
+        [ac_save_CXX="$CXX"
+         CXX="$CXX $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXX="$ac_save_CXX"])
+      if eval test x\$$cachevar = xyes; then
+        CXX="$CXX $switch"
+        if test -n "$CXXCPP" ; then
+          CXXCPP="$CXXCPP $switch"
+        fi
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+
+  m4_if([$2], [ext], [], [dnl
+  if test x$ac_success = xno; then
+    dnl HP's aCC needs +std=c++11 according to:
+    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
+    dnl Cray's crayCC needs "-h std=c++11"
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
+        cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+        AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                       $cachevar,
+          [ac_save_CXX="$CXX"
+           CXX="$CXX $switch"
+           AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+            [eval $cachevar=yes],
+            [eval $cachevar=no])
+           CXX="$ac_save_CXX"])
+        if eval test x\$$cachevar = xyes; then
+          CXX="$CXX $switch"
+          if test -n "$CXXCPP" ; then
+            CXXCPP="$CXXCPP $switch"
+          fi
+          ac_success=yes
+          break
+        fi
+      done
+      if test x$ac_success = xyes; then
+        break
+      fi
+    done
+  fi])
+  AC_LANG_POP([C++])
+  if test x$ax_cxx_compile_cxx$1_required = xtrue; then
+    if test x$ac_success = xno; then
+      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
+    fi
+  fi
+  if test x$ac_success = xno; then
+    HAVE_CXX$1=0
+    AC_MSG_NOTICE([No compiler with C++$1 support was found])
+  else
+    HAVE_CXX$1=1
+    AC_DEFINE(HAVE_CXX$1,1,
+              [define if the compiler supports basic C++$1 syntax])
+  fi
+  AC_SUBST(HAVE_CXX$1)
+  m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
+])
+
+
+dnl  Test body for checking C++11 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+)
+
+
+dnl  Test body for checking C++14 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+)
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+)
+
+dnl  Tests for new features in C++11
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201103L
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+]])
+
+
+dnl  Tests for new features in C++14
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
+
+// If the compiler admits that it is not ready for C++14, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201402L
+
+#error "This is not a C++14 compiler"
+
+#else
+
+namespace cxx14
+{
+
+  namespace test_polymorphic_lambdas
+  {
+
+    int
+    test()
+    {
+      const auto lambda = [](auto&&... args){
+        const auto istiny = [](auto x){
+          return (sizeof(x) == 1UL) ? 1 : 0;
+        };
+        const int aretiny[] = { istiny(args)... };
+        return aretiny[0];
+      };
+      return lambda(1, 1L, 1.0f, '1');
+    }
+
+  }
+
+  namespace test_binary_literals
+  {
+
+    constexpr auto ivii = 0b0000000000101010;
+    static_assert(ivii == 42, "wrong value");
+
+  }
+
+  namespace test_generalized_constexpr
+  {
+
+    template < typename CharT >
+    constexpr unsigned long
+    strlen_c(const CharT *const s) noexcept
+    {
+      auto length = 0UL;
+      for (auto p = s; *p; ++p)
+        ++length;
+      return length;
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("x") == 1UL, "");
+    static_assert(strlen_c("test") == 4UL, "");
+    static_assert(strlen_c("another\0test") == 7UL, "");
+
+  }
+
+  namespace test_lambda_init_capture
+  {
+
+    int
+    test()
+    {
+      auto x = 0;
+      const auto lambda1 = [a = x](int b){ return a + b; };
+      const auto lambda2 = [a = lambda1(x)](){ return a; };
+      return lambda2();
+    }
+
+  }
+
+  namespace test_digit_separators
+  {
+
+    constexpr auto ten_million = 100'000'000;
+    static_assert(ten_million == 100000000, "");
+
+  }
+
+  namespace test_return_type_deduction
+  {
+
+    auto f(int& x) { return x; }
+    decltype(auto) g(int& x) { return x; }
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static constexpr auto value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static constexpr auto value = true;
+    };
+
+    int
+    test()
+    {
+      auto x = 0;
+      static_assert(is_same<int, decltype(f(x))>::value, "");
+      static_assert(is_same<int&, decltype(g(x))>::value, "");
+      return x;
+    }
+
+  }
+
+}  // namespace cxx14
+
+#endif  // __cplusplus >= 201402L
+
+]])
+
+
+dnl  Tests for new features in C++17
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
+
+// If the compiler admits that it is not ready for C++17, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus <= 201402L
+
+#error "This is not a C++17 compiler"
+
+#else
+
+#if defined(__clang__)
+  #define REALLY_CLANG
+#else
+  #if defined(__GNUC__)
+    #define REALLY_GCC
+  #endif
+#endif
+
+#include <initializer_list>
+#include <utility>
+#include <type_traits>
+
+namespace cxx17
+{
+
+#if !defined(REALLY_CLANG)
+  namespace test_constexpr_lambdas
+  {
+
+    // TODO: test it with clang++ from git
+
+    constexpr int foo = [](){return 42;}();
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+  namespace test::nested_namespace::definitions
+  {
+
+  }
+
+  namespace test_fold_expression
+  {
+
+    template<typename... Args>
+    int multiply(Args... args)
+    {
+      return (args * ... * 1);
+    }
+
+    template<typename... Args>
+    bool all(Args... args)
+    {
+      return (args && ...);
+    }
+
+  }
+
+  namespace test_extended_static_assert
+  {
+
+    static_assert (true);
+
+  }
+
+  namespace test_auto_brace_init_list
+  {
+
+    auto foo = {5};
+    auto bar {5};
+
+    static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
+    static_assert(std::is_same<int, decltype(bar)>::value);
+  }
+
+  namespace test_typename_in_template_template_parameter
+  {
+
+    template<template<typename> typename X> struct D;
+
+  }
+
+  namespace test_fallthrough_nodiscard_maybe_unused_attributes
+  {
+
+    int f1()
+    {
+      return 42;
+    }
+
+    [[nodiscard]] int f2()
+    {
+      [[maybe_unused]] auto unused = f1();
+
+      switch (f1())
+      {
+      case 17:
+        f1();
+        [[fallthrough]];
+      case 42:
+        f1();
+      }
+      return f1();
+    }
+
+  }
+
+  namespace test_extended_aggregate_initialization
+  {
+
+    struct base1
+    {
+      int b1, b2 = 42;
+    };
+
+    struct base2
+    {
+      base2() {
+        b3 = 42;
+      }
+      int b3;
+    };
+
+    struct derived : base1, base2
+    {
+        int d;
+    };
+
+    derived d1 {{1, 2}, {}, 4};  // full initialization
+    derived d2 {{}, {}, 4};      // value-initialized bases
+
+  }
+
+  namespace test_general_range_based_for_loop
+  {
+
+    struct iter
+    {
+      int i;
+
+      int& operator* ()
+      {
+        return i;
+      }
+
+      const int& operator* () const
+      {
+        return i;
+      }
+
+      iter& operator++()
+      {
+        ++i;
+        return *this;
+      }
+    };
+
+    struct sentinel
+    {
+      int i;
+    };
+
+    bool operator== (const iter& i, const sentinel& s)
+    {
+      return i.i == s.i;
+    }
+
+    bool operator!= (const iter& i, const sentinel& s)
+    {
+      return !(i == s);
+    }
+
+    struct range
+    {
+      iter begin() const
+      {
+        return {0};
+      }
+
+      sentinel end() const
+      {
+        return {5};
+      }
+    };
+
+    void f()
+    {
+      range r {};
+
+      for (auto i : r)
+      {
+        [[maybe_unused]] auto v = i;
+      }
+    }
+
+  }
+
+  namespace test_lambda_capture_asterisk_this_by_value
+  {
+
+    struct t
+    {
+      int i;
+      int foo()
+      {
+        return [*this]()
+        {
+          return i;
+        }();
+      }
+    };
+
+  }
+
+  namespace test_enum_class_construction
+  {
+
+    enum class byte : unsigned char
+    {};
+
+    byte foo {42};
+
+  }
+
+  namespace test_constexpr_if
+  {
+
+    template <bool cond>
+    int f ()
+    {
+      if constexpr(cond)
+      {
+        return 13;
+      }
+      else
+      {
+        return 42;
+      }
+    }
+
+  }
+
+  namespace test_selection_statement_with_initializer
+  {
+
+    int f()
+    {
+      return 13;
+    }
+
+    int f2()
+    {
+      if (auto i = f(); i > 0)
+      {
+        return 3;
+      }
+
+      switch (auto i = f(); i + 4)
+      {
+      case 17:
+        return 2;
+
+      default:
+        return 1;
+      }
+    }
+
+  }
+
+#if !defined(REALLY_CLANG)
+  namespace test_template_argument_deduction_for_class_templates
+  {
+
+    // TODO: test it with clang++ from git
+
+    template <typename T1, typename T2>
+    struct pair
+    {
+      pair (T1 p1, T2 p2)
+        : m1 {p1},
+          m2 {p2}
+      {}
+
+      T1 m1;
+      T2 m2;
+    };
+
+    void f()
+    {
+      [[maybe_unused]] auto p = pair{13, 42u};
+    }
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+  namespace test_non_type_auto_template_parameters
+  {
+
+    template <auto n>
+    struct B
+    {};
+
+    B<5> b1;
+    B<'a'> b2;
+
+  }
+
+#if !defined(REALLY_CLANG)
+  namespace test_structured_bindings
+  {
+
+    // TODO: test it with clang++ from git
+
+    int arr[2] = { 1, 2 };
+    std::pair<int, int> pr = { 1, 2 };
+
+    auto f1() -> int(&)[2]
+    {
+      return arr;
+    }
+
+    auto f2() -> std::pair<int, int>&
+    {
+      return pr;
+    }
+
+    struct S
+    {
+      int x1 : 2;
+      volatile double y1;
+    };
+
+    S f3()
+    {
+      return {};
+    }
+
+    auto [ x1, y1 ] = f1();
+    auto& [ xr1, yr1 ] = f1();
+    auto [ x2, y2 ] = f2();
+    auto& [ xr2, yr2 ] = f2();
+    const auto [ x3, y3 ] = f3();
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+#if !defined(REALLY_CLANG)
+  namespace test_exception_spec_type_system
+  {
+
+    // TODO: test it with clang++ from git
+
+    struct Good {};
+    struct Bad {};
+
+    void g1() noexcept;
+    void g2();
+
+    template<typename T>
+    Bad
+    f(T*, T*);
+
+    template<typename T1, typename T2>
+    Good
+    f(T1*, T2*);
+
+    static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
+
+  }
+#endif // !defined(REALLY_CLANG)
+
+  namespace test_inline_variables
+  {
+
+    template<class T> void f(T)
+    {}
+
+    template<class T> inline T g(T)
+    {
+      return T{};
+    }
+
+    template<> inline void f<>(int)
+    {}
+
+    template<> int g<>(int)
+    {
+      return 5;
+    }
+
+  }
+
+}  // namespace cxx17
+
+#endif  // __cplusplus <= 201402L
+
+]])
diff --git a/config/config.mk.in b/config/config.mk.in
index 8d920647..619cecd0 100644
--- a/config/config.mk.in
+++ b/config/config.mk.in
@@ -92,11 +92,21 @@ endif
 ENABLE_XMP = @ENABLE_XMP@
 
 ifdef ENABLE_XMP
-        XMPSDK_LIBRARY = xmpsdk
         XMPSDK_DIR = $(top_srcdir)/xmpsdk
         XMPSDK_CPPFLAGS = -I$(XMPSDK_DIR)/include
-        XMPSDK_LDFLAGS = -L$(XMPSDK_DIR)/src
-        XMPSDK_LIBS = -l$(XMPSDK_LIBRARY)
+        XMPSDK_LDFLAGS = -L$(XMPSDK_DIR)
+        XMPSDK_LIBRARIES = -lXMPCore -lXMPFiles
+        XMPSDK_STATIC_LIBS = $(XMPSDK_DIR)/libXMPCore.a $(XMPSDK_DIR)/libXMPFiles.a
+        ifeq ($(OS),Windows_NT)
+                XMPSDK_CPPFLAGS += -DWIN_ENV=1 -DXMP_WinBuild=1
+        else
+                UNAME_S := $(shell uname -s)
+                ifeq ($(UNAME_S),Linux)
+                        XMPSDK_CPPFLAGS += -DUNIX_ENV=1 -DXMP_UNIXBuild=1
+                else
+                        XMPSDK_CPPFLAGS += -DMAC_ENV=1 -DXMP_MacBuild=1
+                endif
+        endif
 else
         # Enable additional warnings. XMP Toolkit doesn't compile
         # with these.
diff --git a/config/configure.ac b/config/configure.ac
index 9d325624..e9507753 100644
--- a/config/configure.ac
+++ b/config/configure.ac
@@ -16,6 +16,9 @@ AC_CONFIG_SRCDIR([src/exif.cpp])
 AC_CONFIG_HEADER([./config/config.h])
 AC_CONFIG_AUX_DIR([./config])
 
+AC_CHECK_FILES([${srcdir}/xmpsdk/include/XMP.hpp], , [echo "Did not find XMP SDK headers"; exit -1])
+AC_CHECK_FILES([${srcdir}/xmpsdk/libXMPCore.a ${srcdir}/xmpsdk/libXMPFiles.a], , [echo "Did not find XMP SDK static lib"; exit -1])
+
 # ---------------------------------------------------------------------------
 # Checks for programs.
 # ---------------------------------------------------------------------------
@@ -23,6 +26,7 @@ AC_CONFIG_AUX_DIR([./config])
 ac_cv_prog_cxx_g=no
 AC_PROG_CXX
 AC_PROG_CXXCPP
+AX_CXX_COMPILE_STDCXX(11, noext, optional)
 # Don't use -g to compile C code
 ac_cv_prog_cc_g=no
 AC_PROG_CC
@@ -145,12 +149,6 @@ AC_ARG_ENABLE(commercial,
 AC_MSG_RESULT($COMMERCIAL_VERSION)
 AC_SUBST(COMMERCIAL_VERSION,$COMMERCIAL_VERSION)
 
-AC_MSG_CHECKING([whether to enable XMP support (requires expat)])
-AC_ARG_ENABLE(xmp,
-    [  --disable-xmp           do not compile XMP support and the XMP Toolkit ],
-    USE_XMP_TOOLKIT=$enableval, USE_XMP_TOOLKIT=yes)
-AC_MSG_RESULT($USE_XMP_TOOLKIT)
-
 AC_MSG_CHECKING([whether to compile with video support])
 AC_ARG_ENABLE(video,
     [  --enable-video          compile with video support ],
@@ -266,8 +264,6 @@ AC_ARG_WITH(expat,
   fi
 ])
 
-ENABLE_XMP=
-if test "$USE_XMP_TOOLKIT" = "yes"; then
     # Check for expat library
     found_expat=yes
     EXPAT_CPPFLAGS=
@@ -286,17 +282,13 @@ if test "$USE_XMP_TOOLKIT" = "yes"; then
         PTHREAD="-lpthread"
     fi
     if test "$with_expat" = "no" -o "$found_expat" = "no"; then
-        AC_MSG_ERROR(either specify a valid expat installation with --with-expat=DIR or disable XMP support with --disable-xmp)
+    AC_MSG_ERROR(either specify a valid expat installation with --with-expat=DIR)
     fi
-    AC_DEFINE(HAVE_XMP_TOOLKIT,1)
-    ENABLE_XMP=1
     AC_SUBST(EXPAT_CPPFLAGS)
     AC_SUBST(EXPAT_LDFLAGS)
     AC_SUBST(EXPAT_LIBS)
     AC_CHECK_LIB(pthread, pthread_create, [PTHREAD_LIBS+=-lpthread])
     AC_SUBST(PTHREAD_LIBS)
-fi
-AC_SUBST(ENABLE_XMP)
 
 CPPFLAGS=${_cppflags}
 LDFLAGS=${_ldflags}
@@ -355,6 +347,13 @@ AC_DEFUN([AX_GCC_VERSION], [
   AC_SUBST([GCC_VERSION])
 ])
 
+AC_ARG_ENABLE(stdcpp11,
+    [  --disable-stdcpp11    do not use the c++11 standard ],
+    STDCPP11_SUPPORT=$enableval, STDCPP11_SUPPORT=$visibility)
+AC_MSG_RESULT($STDCPP11_SUPPORT)
+if test "$STDCPP11_SUPPORT" = "yes"; then
+    CPPFLAGS="${CPPFLAGS} -std=c++11 -DEXV_USING_CPP_ELEVEN"
+else
 # 1188 v0.26 uses c++98
 # 1188 v0.27 should have an option to specify versions such as c++11
 case "$host_os" in
@@ -371,6 +370,7 @@ case "$host_os" in
         fi
     ;;
 esac
+fi
 
 # ---------------------------------------------------------------------------
 # Create output files.
@@ -426,17 +426,6 @@ yes) echo "-- Nikon lens database............ YES" ;;
 *)   echo "-- Nikon lens database............ NO" ;;
 esac
 
-case "$USE_XMP_TOOLKIT" in
-yes) echo "-- XMP metadata support........... YES" ;;
-*)   echo "-- XMP metadata support........... NO"
-     echo ""
-     echo "Expat is required for XMP support. Make sure the Expat header"
-     echo "files are installed and use --with-expat=DIR if it is in a"
-     echo "non-standard location. You can get Expat from"
-     echo "http://expat.sourceforge.net/"
-     echo "" ;;
-esac
-
 case "x$ENABLE_VIDEO" in
 x1)  echo "-- Video support.................. YES" ;;
 *)   echo "-- Video support.................. NO"
diff --git a/contrib/cmake/msvc/ReadMe.txt b/contrib/cmake/msvc/ReadMe.txt
index 25dbf076..5f9d93ca 100755
--- a/contrib/cmake/msvc/ReadMe.txt
+++ b/contrib/cmake/msvc/ReadMe.txt
@@ -172,7 +172,6 @@ How to use this
   C:\cygwin64\home\rmills\gnu\exiv2\trunk>grep OPTION CMakeLists.txt
   OPTION( EXIV2_ENABLE_SHARED        "Build exiv2 as a shared library (dll)"                 ON  )
   OPTION( EXIV2_ENABLE_XMP           "Build with XMP metadata support"                       ON  )
-  OPTION( EXIV2_ENABLE_LIBXMP        "Build a static convenience Library for XMP"            ON  )
   OPTION( EXIV2_ENABLE_VIDEO         "Build with video support"                              OFF )
   OPTION( EXIV2_ENABLE_PNG           "Build with png support (requires libz)"                ON  )
   OPTION( EXIV2_ENABLE_NLS           "Build native language support (requires gettext)"      ON  )
diff --git a/contrib/organize/helpers.cpp b/contrib/organize/helpers.cpp
index 7f08e429..6ca7caaf 100644
--- a/contrib/organize/helpers.cpp
+++ b/contrib/organize/helpers.cpp
@@ -35,7 +35,7 @@
 #include <exiv2/exif.hpp>
 #include <exiv2/iptc.hpp>
 #include <exiv2/tags.hpp>
-//#include <exiv2/xmp.hpp>
+//#include <exiv2/xmp_exiv2.hpp>
 #include <cassert>
 #include <sstream>
 #include <ctime>
diff --git a/include/exiv2/basicio.hpp b/include/exiv2/basicio.hpp
index 95713bfc..9824936c 100644
--- a/include/exiv2/basicio.hpp
+++ b/include/exiv2/basicio.hpp
@@ -67,8 +67,11 @@ namespace Exiv2 {
     class EXIV2API BasicIo {
     public:
         //! BasicIo auto_ptr type
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<BasicIo> AutoPtr;
+#else
         typedef std::auto_ptr<BasicIo> AutoPtr;
-
+#endif
         //! Seek starting positions
         enum Position { beg, cur, end };
 
diff --git a/include/exiv2/datasets.hpp b/include/exiv2/datasets.hpp
index 46a323c5..f03c17ac 100644
--- a/include/exiv2/datasets.hpp
+++ b/include/exiv2/datasets.hpp
@@ -280,7 +280,11 @@ namespace Exiv2 {
     class EXIV2API IptcKey : public Key {
     public:
         //! Shortcut for an %IptcKey auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<IptcKey> AutoPtr;
+#else
         typedef std::auto_ptr<IptcKey> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
diff --git a/include/exiv2/exiv2.hpp b/include/exiv2/exiv2.hpp
index 9930b8b3..d4cc566e 100644
--- a/include/exiv2/exiv2.hpp
+++ b/include/exiv2/exiv2.hpp
@@ -70,7 +70,7 @@
 #include "exiv2/types.hpp"
 #include "exiv2/value.hpp"
 #include "exiv2/version.hpp"
-#include "exiv2/xmp.hpp"
+#include "exiv2/xmp_exiv2.hpp"
 #include "exiv2/xmpsidecar.hpp"
 
 #endif                                  // #ifndef EXIV2_HPP_
diff --git a/include/exiv2/image.hpp b/include/exiv2/image.hpp
index 4040d524..76e37736 100644
--- a/include/exiv2/image.hpp
+++ b/include/exiv2/image.hpp
@@ -31,7 +31,7 @@
 #include "basicio.hpp"
 #include "exif.hpp"
 #include "iptc.hpp"
-#include "xmp.hpp"
+#include "xmp_exiv2.hpp"
 
 // + standard includes
 #include <string>
@@ -82,7 +82,11 @@ namespace Exiv2 {
     class EXIV2API Image {
     public:
         //! Image auto_ptr type
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Image> AutoPtr;
+#else
         typedef std::auto_ptr<Image> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
diff --git a/include/exiv2/metadatum.hpp b/include/exiv2/metadatum.hpp
index 4e7b2f5c..d520e297 100644
--- a/include/exiv2/metadatum.hpp
+++ b/include/exiv2/metadatum.hpp
@@ -60,7 +60,11 @@ namespace Exiv2 {
     class EXIV2API Key {
     public:
         //! Shortcut for a %Key auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Key> AutoPtr;
+#else
         typedef std::auto_ptr<Key> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
diff --git a/include/exiv2/properties.hpp b/include/exiv2/properties.hpp
index 415ab4ab..f451a96c 100644
--- a/include/exiv2/properties.hpp
+++ b/include/exiv2/properties.hpp
@@ -249,7 +249,11 @@ namespace Exiv2 {
     class EXIV2API XmpKey : public Key {
     public:
         //! Shortcut for an %XmpKey auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<XmpKey> AutoPtr;
+#else
         typedef std::auto_ptr<XmpKey> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
diff --git a/include/exiv2/tags.hpp b/include/exiv2/tags.hpp
index 0c1b487a..dd746cc1 100644
--- a/include/exiv2/tags.hpp
+++ b/include/exiv2/tags.hpp
@@ -150,7 +150,11 @@ namespace Exiv2 {
     class EXIV2API ExifKey : public Key {
     public:
         //! Shortcut for an %ExifKey auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<ExifKey> AutoPtr;
+#else
         typedef std::auto_ptr<ExifKey> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
diff --git a/include/exiv2/value.hpp b/include/exiv2/value.hpp
index 64a8ca7f..a9ba7ccc 100644
--- a/include/exiv2/value.hpp
+++ b/include/exiv2/value.hpp
@@ -63,7 +63,11 @@ namespace Exiv2 {
     class EXIV2API Value {
     public:
         //! Shortcut for a %Value auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Value> AutoPtr;
+#else
         typedef std::auto_ptr<Value> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -265,7 +269,11 @@ namespace Exiv2 {
     class EXIV2API DataValue : public Value {
     public:
         //! Shortcut for a %DataValue auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<DataValue> AutoPtr;
+#else
         typedef std::auto_ptr<DataValue> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -352,7 +360,11 @@ namespace Exiv2 {
     class EXIV2API StringValueBase : public Value {
     public:
         //! Shortcut for a %StringValueBase auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<StringValueBase> AutoPtr;
+#else
         typedef std::auto_ptr<StringValueBase> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -434,7 +446,11 @@ namespace Exiv2 {
     class EXIV2API StringValue : public StringValueBase {
     public:
         //! Shortcut for a %StringValue auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<StringValue> AutoPtr;
+#else
         typedef std::auto_ptr<StringValue> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -466,7 +482,11 @@ namespace Exiv2 {
     class EXIV2API AsciiValue : public StringValueBase {
     public:
         //! Shortcut for a %AsciiValue auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<AsciiValue> AutoPtr;
+#else
         typedef std::auto_ptr<AsciiValue> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -553,7 +573,11 @@ namespace Exiv2 {
         }; // class CharsetInfo
 
         //! Shortcut for a %CommentValue auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<CommentValue> AutoPtr;
+#else
         typedef std::auto_ptr<CommentValue> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -640,7 +664,11 @@ namespace Exiv2 {
     class EXIV2API XmpValue : public Value {
     public:
         //! Shortcut for a %XmpValue auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<XmpValue> AutoPtr;
+#else
         typedef std::auto_ptr<XmpValue> AutoPtr;
+#endif
 
         //! XMP array types.
         enum XmpArrayType { xaNone, xaAlt, xaBag, xaSeq };
@@ -731,7 +759,11 @@ namespace Exiv2 {
     class EXIV2API XmpTextValue : public XmpValue {
     public:
         //! Shortcut for a %XmpTextValue auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<XmpTextValue> AutoPtr;
+#else
         typedef std::auto_ptr<XmpTextValue> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -813,7 +845,11 @@ namespace Exiv2 {
     class EXIV2API XmpArrayValue : public XmpValue {
     public:
         //! Shortcut for a %XmpArrayValue auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<XmpArrayValue> AutoPtr;
+#else
         typedef std::auto_ptr<XmpArrayValue> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -910,7 +946,11 @@ namespace Exiv2 {
     class EXIV2API LangAltValue : public XmpValue {
     public:
         //! Shortcut for a %LangAltValue auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<LangAltValue> AutoPtr;
+#else
         typedef std::auto_ptr<LangAltValue> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -998,7 +1038,11 @@ namespace Exiv2 {
     class EXIV2API DateValue : public Value {
     public:
         //! Shortcut for a %DateValue auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<DateValue> AutoPtr;
+#else
         typedef std::auto_ptr<DateValue> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -1099,7 +1143,11 @@ namespace Exiv2 {
     class EXIV2API TimeValue : public Value {
     public:
         //! Shortcut for a %TimeValue auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<TimeValue> AutoPtr;
+#else
         typedef std::auto_ptr<TimeValue> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -1255,7 +1303,11 @@ namespace Exiv2 {
     class ValueType : public Value {
     public:
         //! Shortcut for a %ValueType\<T\> auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<ValueType<T> > AutoPtr;
+#else
         typedef std::auto_ptr<ValueType<T> > AutoPtr;
+#endif
 
         //! @name Creators
         //@{
diff --git a/include/exiv2/xmp.hpp b/include/exiv2/xmp_exiv2.hpp
similarity index 98%
rename from include/exiv2/xmp.hpp
rename to include/exiv2/xmp_exiv2.hpp
index 05dbbc10..3dc6cfa7 100644
--- a/include/exiv2/xmp.hpp
+++ b/include/exiv2/xmp_exiv2.hpp
@@ -1,6 +1,6 @@
 // ***************************************************************** -*- C++ -*-
 /*
- * Copyright (C) 2004-2017 Andreas Huggel <ahuggel@gmx.net>
+ * Copyright (C) 2004-2015 Andreas Huggel <ahuggel@gmx.net>
  *
  * This program is part of the Exiv2 distribution.
  *
@@ -19,15 +19,15 @@
  * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
  */
 /*!
-  @file    xmp.hpp
+  @file    xmp_exiv2.hpp
   @brief   Encoding and decoding of XMP data
   @version $Rev: 3090 $
   @author  Andreas Huggel (ahu)
            <a href="mailto:ahuggel@gmx.net">ahuggel@gmx.net</a>
   @date    13-Jul-07, ahu: created
  */
-#ifndef XMP_HPP_
-#define XMP_HPP_
+#ifndef XMP_EXIV2_HPP_
+#define XMP_EXIV2_HPP_
 
 // *****************************************************************************
 // included header files
@@ -438,4 +438,4 @@ namespace Exiv2 {
 
 }                                       // namespace Exiv2
 
-#endif                                  // #ifndef XMP_HPP_
+#endif                                  // #ifndef XMP_EXIV2_HPP_
diff --git a/samples/CMakeLists.txt b/samples/CMakeLists.txt
index edc7feee..86611f5b 100644
--- a/samples/CMakeLists.txt
+++ b/samples/CMakeLists.txt
@@ -49,7 +49,7 @@ FOREACH(entry ${SAMPLES})
     STRING( REPLACE ".cpp" "" target ${entry})
     ADD_EXECUTABLE( ${target} ${target}.cpp )
     ADD_TEST( ${target}_test ${target} )
-    TARGET_LINK_LIBRARIES( ${target} ${PRIVATE_VAR} exiv2lib ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES})
+    TARGET_LINK_LIBRARIES( ${target} ${PRIVATE_VAR} exiv2lib ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES} ${XMPLIBS} )
     INSTALL( TARGETS ${target} ${INSTALL_TARGET_STANDARD_ARGS} )
 ENDFOREACH(entry ${SAMPLES})
 
@@ -62,25 +62,25 @@ ENDIF( MSVC )
 
 SET( MC_SRC ${MC_SRC} metacopy.cpp ../src/utils.cpp )
 ADD_EXECUTABLE( metacopy ${MC_SRC} )
-TARGET_LINK_LIBRARIES( metacopy ${PRIVATE_VAR} exiv2lib ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES})
+TARGET_LINK_LIBRARIES( metacopy ${PRIVATE_VAR} exiv2lib ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES} ${XMPLIBS} )
 INSTALL( TARGETS metacopy ${INSTALL_TARGET_STANDARD_ARGS} )
 
 SET   ( PATHTEST_SRC             ${PATHTEST_SRC}  path-test.cpp ../src/utils.cpp )
 ADD_EXECUTABLE       ( pathtest  ${PATHTEST_SRC} )
 SET_TARGET_PROPERTIES( pathtest  PROPERTIES OUTPUT_NAME path-test )
-TARGET_LINK_LIBRARIES( pathtest  ${PRIVATE_VAR} exiv2lib ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES})
+TARGET_LINK_LIBRARIES( pathtest  ${PRIVATE_VAR} exiv2lib ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES} ${XMPLIBS} )
 INSTALL      ( TARGETS pathtest  ${INSTALL_TARGET_STANDARD_ARGS} )
 
 SET( EXIV2JSON_SRC     exiv2json.cpp Jzon.cpp )
 ADD_EXECUTABLE(        exiv2json ${EXIV2JSON_SRC} )
 SET_TARGET_PROPERTIES( exiv2json PROPERTIES OUTPUT_NAME exiv2json )
-TARGET_LINK_LIBRARIES( exiv2json ${PRIVATE_VAR} ${PRIVATE_VAR} exiv2lib ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES})
+TARGET_LINK_LIBRARIES( exiv2json ${PRIVATE_VAR} ${PRIVATE_VAR} exiv2lib ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES} ${XMPLIBS} )
 INSTALL( TARGETS       exiv2json ${INSTALL_TARGET_STANDARD_ARGS} )
 
 SET( GEOTAG_SRC        geotag.cpp )
 ADD_EXECUTABLE(        geotag    ${GEOTAG_SRC} )
 SET_TARGET_PROPERTIES( geotag    PROPERTIES OUTPUT_NAME geotag )
-TARGET_LINK_LIBRARIES( geotag    ${PRIVATE_VAR} exiv2lib ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES})
+TARGET_LINK_LIBRARIES( geotag    ${PRIVATE_VAR} exiv2lib ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES} ${XMPLIBS} )
 INSTALL( TARGETS       geotag    ${INSTALL_TARGET_STANDARD_ARGS} )
 
 # ******************************************************************************
@@ -90,4 +90,3 @@ INSTALL( FILES exiv2samples.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 )
 # That's all Folks!
 ##
 
-
diff --git a/samples/Makefile b/samples/Makefile
index 1ad6364d..c8993fec 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -118,7 +118,7 @@ DEP = $(BINSRC:%.cpp=$(DEPDIR)/%.d) $(OTHERSRC:%.cpp=$(DEPDIR)/%.d) $(DEPDIR)/Jz
 endif
 
 PREFIX = /usr/local/lib
-LINK.cc += -rpath $(PREFIX) -L$(PREFIX)
+LINK.cc += -rdynamic -rpath $(PREFIX) -L$(PREFIX)
 
 # TODO: This should really not be here. We should use the installed headers
 # to build the samples. Some errors only show up in this scenario, e.g., errors
diff --git a/samples/metacopy.cpp b/samples/metacopy.cpp
index 4acda313..c1f2c99a 100644
--- a/samples/metacopy.cpp
+++ b/samples/metacopy.cpp
@@ -58,7 +58,11 @@ try {
     Exiv2::BasicIo::AutoPtr memIo(new Exiv2::MemIo);
     memIo->transfer(*fileIo);
 
+#ifdef EXV_USING_CPP_ELEVEN
+    Exiv2::Image::AutoPtr readImg = Exiv2::ImageFactory::open(std::move(memIo));
+#else
     Exiv2::Image::AutoPtr readImg = Exiv2::ImageFactory::open(memIo);
+#endif
     assert(readImg.get() != 0);
     readImg->readMetadata();
 
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7ae4f56d..0f9a8565 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -34,6 +34,7 @@ SET( LIBEXIV2_PRIVATE_HDR canonmn_int.hpp
                           tifffwd_int.hpp
                           tiffimage_int.hpp
                           tiffvisitor_int.hpp
+                          MD5.h
    )
 
 # Add standalone C++ header files to this list
@@ -79,7 +80,7 @@ SET( LIBEXIV2_HDR         ${CMAKE_CURRENT_LIST_DIR}/../include/exiv2/asfvideo.hp
                           ${CMAKE_CURRENT_LIST_DIR}/../include/exiv2/value.hpp
                           ${CMAKE_CURRENT_LIST_DIR}/../include/exiv2/version.hpp
                           ${CMAKE_CURRENT_LIST_DIR}/../include/exiv2/webpimage.hpp
-                          ${CMAKE_CURRENT_LIST_DIR}/../include/exiv2/xmp.hpp
+                          ${CMAKE_CURRENT_LIST_DIR}/../include/exiv2/xmp_exiv2.hpp
                           ${CMAKE_CURRENT_LIST_DIR}/../include/exiv2/xmpsidecar.hpp
                           ${CMAKE_CURRENT_LIST_DIR}/../include/exiv2/utilsvideo.hpp
    )
@@ -139,9 +140,10 @@ SET( LIBEXIV2_SRC         asfvideo.cpp
                           value.cpp
                           version.cpp
                           webpimage.cpp
-                          xmp.cpp
+                          xmp_exiv2.cpp
                           xmpsidecar.cpp
                           utilsvideo.cpp
+                          MD5.cpp
    )
 
 IF( EXIV2_ENABLE_WEBREADY )
@@ -186,14 +188,8 @@ ENDIF( EXIV2_ENABLE_PNG )
 
 INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
 
-##
-# add xmp source if xmp is requested and xmp library not built
-IF( EXIV2_ENABLE_XMP )
-    IF( NOT EXIV2_ENABLE_LIBXMP )
-        SET( LIBEXIV2_SRC ${XMPSRC} ${LIBEXIV2_SRC} )
-    ENDIF( NOT EXIV2_ENABLE_LIBXMP )
-ENDIF( EXIV2_ENABLE_XMP )
 
+IF ( EXV_HAS_XMP_SDK_LIBS )
 ##
 # Create source file lists for applications
 # exiv2 application
@@ -213,17 +209,22 @@ SET( CONNTEST             ../samples/conntest.cpp)
 SET( EXIFPRINT            ../samples/exifprint.cpp)
 # cmdfiletest application
 SET( REMOTETEST           ../samples/remotetest.cpp)
+ENDIF()
 
 ##
 # modify source lists to suit environment
 IF(NOT HAVE_TIMEGM )
     SET( LIBEXIV2_SRC     ${LIBEXIV2_SRC} localtime.c    )
+    IF ( EXV_HAS_XMP_SDK_LIBS )
     SET( EXIV2_SRC        ${EXIV2_SRC}    localtime.c    )
+    ENDIF()
     SET( PATHTEST_SRC     ${PATHTEST_SRC} localtime.c    )
 ENDIF( NOT HAVE_TIMEGM )
 
 IF( MSVC )
+    IF ( EXV_HAS_XMP_SDK_LIBS )
     SET( EXIV2_SRC        ${EXIV2_SRC}    getopt_win32.c )
+    ENDIF()
     SET( LIBEXIV2_SRC     ${LIBEXIV2_SRC} getopt_win32.c )
 ENDIF( MSVC )
 
@@ -258,34 +259,29 @@ ENDIF()
 if ( MSVC )
     source_group("Header Files" FILES ${LIBEXIV2_HDR} )
     TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${ZLIB_LIBRARIES} )
-    TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${EXPAT_LIBRARIES} )
     source_group("Header Files" FILES ${LIBCURL_HDR} )
     TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${CURL_LIBRARIES} )
     source_group("Header Files" FILES ${SSH_HDR} )
     TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${SSH_LIBRARIES} )
 else()
     if ( UNIX AND NOT FREEBSD )
-        TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} dl ${EXPAT_LIBRARIES} )
         TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} dl ${CURL_LIBRARIES} )
         TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} dl ${SSH_LIBRARIES} )
         TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} dl ${CMAKE_THREAD_LIBS_INIT} )
     else()
-        TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${EXPAT_LIBRARIES} )
         TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${CURL_LIBRARIES} )
         TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${SSH_LIBRARIES} )
         TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${CMAKE_THREAD_LIBS_INIT} )
     endif()
 endif()
 
-if( EXIV2_ENABLE_LIBXMP )
-    ADD_DEPENDENCIES( exiv2lib xmp )
+if( EXIV2_ENABLE_XMP )
     if  ( MSVC )
         LINK_DIRECTORIES(${LIBRARY_OUTPUT_PATH}/$(ConfigurationName))
     else()
-        ADD_DEPENDENCIES( exiv2lib xmp)
-        TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${EXPAT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
+        TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${CMAKE_THREAD_LIBS_INIT})
     endif(MSVC)
-    TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} xmp )
+    TARGET_LINK_LIBRARIES( exiv2lib ${PRIVATE_VAR} ${XMPLIBS} )
 ENDIF()
 
 IF( EXIV2_ENABLE_PNG )
@@ -315,16 +311,21 @@ INSTALL( TARGETS exiv2lib ${INSTALL_TARGET_STANDARD_ARGS} )
 include(../CMake_msvc.txt)
 msvc_runtime_configure(${EXIV2_ENABLE_SHARED} ${EXIV2_ENABLE_DYNAMIC_RUNTIME})
 
-# ******************************************************************************
-# exiv2 application
+ # ******************************************************************************
+ # exiv2 application
+
+IF ( EXV_HAS_XMP_SDK_LIBS )
 ADD_EXECUTABLE( exiv2 ${EXIV2_SRC}  ${EXIV2_HDR} )
-TARGET_LINK_LIBRARIES( exiv2 exiv2lib ${LIBINTL_LIBRARIES} )
+TARGET_LINK_LIBRARIES( exiv2 exiv2lib )
 INSTALL( TARGETS exiv2 ${INSTALL_TARGET_STANDARD_ARGS} )
+ENDIF()
 
 # ******************************************************************************
 # connection test application
+IF ( EXV_HAS_XMP_SDK_LIBS )
 ADD_EXECUTABLE( conntest ${CONNTEST} )
-TARGET_LINK_LIBRARIES( conntest ${PRIVATE_VAR}  exiv2lib ${CURL_LIBRARIES} ${SSH_LIBRARIES} ${LIBINTL_LIBRARIES} )
+TARGET_LINK_LIBRARIES( conntest ${PRIVATE_VAR}  exiv2lib ${CURL_LIBRARIES} ${SSH_LIBRARIES})
+ENDIF()
 
 # ******************************************************************************
 # exifprint application
@@ -333,8 +334,10 @@ TARGET_LINK_LIBRARIES( conntest ${PRIVATE_VAR}  exiv2lib ${CURL_LIBRARIES} ${SSH
 
 # ******************************************************************************
 # remotetest application
+IF ( EXV_HAS_XMP_SDK_LIBS )
 ADD_EXECUTABLE( remotetest ${REMOTETEST} )
-TARGET_LINK_LIBRARIES( remotetest exiv2lib ${LIBINTL_LIBRARIES} )
+TARGET_LINK_LIBRARIES( remotetest exiv2lib )
+ENDIF()
 
 # ******************************************************************************
 # Headers
diff --git a/xmpsdk/src/MD5.cpp b/src/MD5.cpp
similarity index 92%
rename from xmpsdk/src/MD5.cpp
rename to src/MD5.cpp
index f162b728..5d4034bb 100644
--- a/xmpsdk/src/MD5.cpp
+++ b/src/MD5.cpp
@@ -20,6 +20,9 @@
  * Still in the public domain.
  */
 
+#ifdef EXV_USING_CPP_ELEVEN
+#include <cstdint>
+#endif
 #include <cstring>
 
 #include "MD5.h"
@@ -46,7 +49,7 @@ byteSwap(UWORD32 *buf, unsigned words)
  * initialization constants.
  */
 void
-MD5Init(struct MD5_CTX *ctx)
+EXIV2_MD5Init(struct MD5_CTX *ctx)
 {
 	ctx->buf[0] = 0x67452301;
 	ctx->buf[1] = 0xefcdab89;
@@ -62,7 +65,7 @@ MD5Init(struct MD5_CTX *ctx)
  * of bytes.
  */
 void
-MD5Update(struct MD5_CTX *ctx, md5byte const *buf, unsigned len)
+EXIV2_MD5Update(struct MD5_CTX *ctx, md5byte const *buf, unsigned len)
 {
 	UWORD32 t;
 
@@ -80,7 +83,7 @@ MD5Update(struct MD5_CTX *ctx, md5byte const *buf, unsigned len)
 	/* First chunk is an odd size */
 	memcpy((md5byte *)ctx->in + 64 - t, buf, t);
 	byteSwap(ctx->in, 16);
-	MD5Transform(ctx->buf, ctx->in);
+	EXIV2_MD5Transform(ctx->buf, ctx->in);
 	buf += t;
 	len -= t;
 
@@ -88,7 +91,7 @@ MD5Update(struct MD5_CTX *ctx, md5byte const *buf, unsigned len)
 	while (len >= 64) {
 		memcpy(ctx->in, buf, 64);
 		byteSwap(ctx->in, 16);
-		MD5Transform(ctx->buf, ctx->in);
+		EXIV2_MD5Transform(ctx->buf, ctx->in);
 		buf += 64;
 		len -= 64;
 	}
@@ -98,11 +101,11 @@ MD5Update(struct MD5_CTX *ctx, md5byte const *buf, unsigned len)
 }
 
 /*
- * Final wrapup - pad to 64-byte boundary with the bit pattern 
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
  * 1 0* (64-bit count of bits processed, MSB-first)
  */
 void
-MD5Final(md5byte digest[16], struct MD5_CTX *ctx)
+EXIV2_MD5Final(md5byte digest[16], struct MD5_CTX *ctx)
 {
 	int count = ctx->bytes[0] & 0x3f;	/* Number of bytes in ctx->in */
 	md5byte *p = (md5byte *)ctx->in + count;
@@ -116,7 +119,7 @@ MD5Final(md5byte digest[16], struct MD5_CTX *ctx)
 	if (count < 0) {	/* Padding forces an extra block */
 		memset(p, 0, count + 8);
 		byteSwap(ctx->in, 16);
-		MD5Transform(ctx->buf, ctx->in);
+		EXIV2_MD5Transform(ctx->buf, ctx->in);
 		p = (md5byte *)ctx->in;
 		count = 56;
 	}
@@ -126,7 +129,7 @@ MD5Final(md5byte digest[16], struct MD5_CTX *ctx)
 	/* Append length in bits and transform */
 	ctx->in[14] = ctx->bytes[0] << 3;
 	ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
-	MD5Transform(ctx->buf, ctx->in);
+	EXIV2_MD5Transform(ctx->buf, ctx->in);
 
 	byteSwap(ctx->buf, 4);
 	memcpy(digest, ctx->buf, 16);
@@ -151,9 +154,13 @@ MD5Final(md5byte digest[16], struct MD5_CTX *ctx)
  * the data and converts bytes into longwords for this routine.
  */
 void
-MD5Transform(UWORD32 buf[4], UWORD32 const in[16])
+EXIV2_MD5Transform(UWORD32 buf[4], UWORD32 const in[16])
 {
+#ifdef EXV_USING_CPP_ELEVEN
+	UWORD32 a, b, c, d;
+#else
 	register UWORD32 a, b, c, d;
+#endif
 
 	a = buf[0];
 	b = buf[1];
diff --git a/xmpsdk/include/MD5.h b/src/MD5.h
similarity index 83%
rename from xmpsdk/include/MD5.h
rename to src/MD5.h
index f6c5e783..772fc157 100644
--- a/xmpsdk/include/MD5.h
+++ b/src/MD5.h
@@ -52,9 +52,9 @@ struct MD5_CTX {
 	UWORD32 in[16];
 };
 
-extern void MD5Init(struct MD5_CTX *context);
-extern void MD5Update(struct MD5_CTX *context, md5byte const *buf, unsigned len);
-extern void MD5Final(unsigned char digest[16], struct MD5_CTX *context);
-extern void MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
+extern void EXIV2_MD5Init(struct MD5_CTX *context);
+extern void EXIV2_MD5Update(struct MD5_CTX *context, md5byte const *buf, unsigned len);
+extern void EXIV2_MD5Final(unsigned char digest[16], struct MD5_CTX *context);
+extern void EXIV2_MD5Transform(UWORD32 buf[4], UWORD32 const in[16]);
 
 #endif
diff --git a/src/Makefile b/src/Makefile
index 1b955140..d1840346 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -88,6 +88,7 @@ CCSRC =  basicio.cpp           \
 	 jp2image.cpp          \
 	 jpgimage.cpp          \
 	 makernote.cpp         \
+	 MD5.cpp               \
 	 metadatum.cpp         \
 	 minoltamn.cpp         \
 	 mrwimage.cpp          \
@@ -121,7 +122,7 @@ CCSRC += sigmamn.cpp       \
 	 value.cpp             \
 	 version.cpp           \
 	 webpimage.cpp         \
-	 xmp.cpp               \
+	 xmp_exiv2.cpp         \
 	 xmpsidecar.cpp
 ifdef ENABLE_VIDEO
 CCSRC += asfvideo.cpp      \
@@ -159,8 +160,8 @@ SHELL = /bin/bash
 .PRECIOUS: %.cpp
 
 CPPFLAGS += $(SSH_CPPFLAGS) $(CURL_CPPFLAGS) $(XMPSDK_CPPFLAGS)
-LDFLAGS  += $(SSH_LDFLAGS) $(CURL_LDFLAGS) $(EXPAT_LDFLAGS) $(XMPSDK_LDFLAGS)
-LIBS     += $(SSH_LIBS) $(CURL_LIBS) $(EXPAT_LIBS) $(XMPSDK_LIBS)
+LDFLAGS  += $(SSH_LDFLAGS) $(CURL_LDFLAGS) $(XMPSDK_LDFLAGS)
+LIBS     += $(SSH_LIBS) $(CURL_LIBS) $(XMPSDK_LIBRARIES)
 
 # Generic variables
 CCHDR := $(CCHDR) $(CCSRC:.cpp=.hpp)
@@ -247,7 +248,7 @@ $(BINARY): %: %.o lib
 
 $(EXIV2EXE): lib $(EXIV2OBJ) $(EXIV2COBJ)
 	mkdir -pv ../bin 2>&1 > /dev/null
-	@$(LIBTOOL) --mode=link $(LINK.cc) -o ../bin/$@ $(LIBRARY) $(EXIV2OBJ) $(EXIV2COBJ) -rpath $(libdir)
+	@$(LIBTOOL) --mode=link $(LINK.cc)  $(EXIV2OBJ) $(EXIV2COBJ) -o ../bin/$@ -rdynamic $(LIBRARY) -rpath $(libdir) -Wl,-rpath,$(top_srcdir)/xmpsdk $(XMPSDK_STATIC_LIBS)
 
 install-header:
 	$(INSTALL_DIRS) $(DESTDIR)$(incdir)
diff --git a/src/actions.cpp b/src/actions.cpp
index 17444c5b..c8653131 100644
--- a/src/actions.cpp
+++ b/src/actions.cpp
@@ -42,7 +42,7 @@ EXIV2_RCSID("@(#) $Id: actions.cpp 4719 2017-03-08 20:42:28Z robinwmills $")
 #include "exif.hpp"
 #include "easyaccess.hpp"
 #include "iptc.hpp"
-#include "xmp.hpp"
+#include "xmp_exiv2.hpp"
 #include "preview.hpp"
 #include "futils.hpp"
 #include "i18n.h"                // NLS support.
@@ -228,7 +228,11 @@ namespace Action {
             Task* t = i->second;
             return t->clone();
         }
+#ifdef EXV_USING_CPP_ELEVEN
+        return Task::AutoPtr(nullptr);
+#else
         return Task::AutoPtr(0);
+#endif
     } // TaskFactory::create
 
     Print::~Print()
@@ -284,7 +288,11 @@ namespace Action {
                       << _("Failed to open the file\n");
             return -1;
         }
+#ifdef EXV_USING_CPP_ELEVEN
+        Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(std::move(path_));
+#else
         Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path_);
+#endif
         assert(image.get() != 0);
         image->readMetadata();
         Exiv2::ExifData& exifData = image->exifData();
@@ -2113,7 +2121,11 @@ namespace {
         if ( bStdin )  Params::instance().getStdin(stdIn);
         Exiv2::BasicIo::AutoPtr ioStdin = Exiv2::BasicIo::AutoPtr(new Exiv2::MemIo(stdIn.pData_,stdIn.size_));
 
+#ifdef EXV_USING_CPP_ELEVEN
+        Exiv2::Image::AutoPtr sourceImage = bStdin ? Exiv2::ImageFactory::open(std::move(ioStdin)) : Exiv2::ImageFactory::open(std::move(source));
+#else
         Exiv2::Image::AutoPtr sourceImage = bStdin ? Exiv2::ImageFactory::open(ioStdin) : Exiv2::ImageFactory::open(source);
+#endif
         assert(sourceImage.get() != 0);
         sourceImage->readMetadata();
 
diff --git a/src/actions.hpp b/src/actions.hpp
index 9cce024c..94d7361a 100644
--- a/src/actions.hpp
+++ b/src/actions.hpp
@@ -75,7 +75,11 @@ namespace Action {
     class Task {
     public:
         //! Shortcut for an auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Task> AutoPtr;
+#else
         typedef std::auto_ptr<Task> AutoPtr;
+#endif
         //! Virtual destructor.
         virtual ~Task();
         //! Virtual copy construction.
@@ -159,7 +163,11 @@ namespace Action {
     public:
         virtual ~Print();
         virtual int run(const std::string& path);
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Print> AutoPtr;
+#else
         typedef std::auto_ptr<Print> AutoPtr;
+#endif
         AutoPtr clone() const;
 
         //! Print the Jpeg comment
@@ -216,7 +224,11 @@ namespace Action {
     public:
         virtual ~Rename();
         virtual int run(const std::string& path);
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Rename> AutoPtr;
+#else
         typedef std::auto_ptr<Rename> AutoPtr;
+#endif
         AutoPtr clone() const;
 
     private:
@@ -228,7 +240,11 @@ namespace Action {
     public:
         virtual ~Adjust();
         virtual int run(const std::string& path);
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Adjust> AutoPtr;
+#else
         typedef std::auto_ptr<Adjust> AutoPtr;
+#endif
         AutoPtr clone() const;
 
     private:
@@ -251,7 +267,11 @@ namespace Action {
     public:
         virtual ~Erase();
         virtual int run(const std::string& path);
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Erase> AutoPtr;
+#else
         typedef std::auto_ptr<Erase> AutoPtr;
+#endif
         AutoPtr clone() const;
 
         /*!
@@ -297,7 +317,11 @@ namespace Action {
     public:
         virtual ~Extract();
         virtual int run(const std::string& path);
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Extract> AutoPtr;
+#else
         typedef std::auto_ptr<Extract> AutoPtr;
+#endif
         AutoPtr clone() const;
 
         /*!
@@ -336,7 +360,11 @@ namespace Action {
     public:
         virtual ~Insert();
         virtual int run(const std::string& path);
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Insert> AutoPtr;
+#else
         typedef std::auto_ptr<Insert> AutoPtr;
+#endif
         AutoPtr clone() const;
 
         /*!
@@ -377,7 +405,11 @@ namespace Action {
     public:
         virtual ~Modify();
         virtual int run(const std::string& path);
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Modify> AutoPtr;
+#else
         typedef std::auto_ptr<Modify> AutoPtr;
+#endif
         AutoPtr clone() const;
         Modify() {}
         //! Apply modification commands to the \em pImage, return 0 if successful.
@@ -410,7 +442,11 @@ namespace Action {
     public:
         virtual ~FixIso();
         virtual int run(const std::string& path);
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<FixIso> AutoPtr;
+#else
         typedef std::auto_ptr<FixIso> AutoPtr;
+#endif
         AutoPtr clone() const;
 
     private:
@@ -428,7 +464,11 @@ namespace Action {
     public:
         virtual ~FixCom();
         virtual int run(const std::string& path);
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<FixCom> AutoPtr;
+#else
         typedef std::auto_ptr<FixCom> AutoPtr;
+#endif
         AutoPtr clone() const;
 
     private:
diff --git a/src/asfvideo.cpp b/src/asfvideo.cpp
index eace7073..2dc38e6e 100644
--- a/src/asfvideo.cpp
+++ b/src/asfvideo.cpp
@@ -296,10 +296,17 @@ namespace Exiv2 {
 
     using namespace Exiv2::Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    AsfVideo::AsfVideo(BasicIo::AutoPtr io)
+        : Image(ImageType::asf, mdNone, std::move(io))
+    {
+    } // AsfVideo::AsfVideo
+#else
     AsfVideo::AsfVideo(BasicIo::AutoPtr io)
         : Image(ImageType::asf, mdNone, io)
     {
     } // AsfVideo::AsfVideo
+#endif
 
     std::string AsfVideo::mimeType() const
     {
@@ -792,7 +799,11 @@ namespace Exiv2 {
 
     Image::AutoPtr newAsfInstance(BasicIo::AutoPtr io, bool /*create*/)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new AsfVideo(std::move(io)));
+#else
         Image::AutoPtr image(new AsfVideo(io));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/bmpimage.cpp b/src/bmpimage.cpp
index 4cbb1acc..5bfeb4f5 100644
--- a/src/bmpimage.cpp
+++ b/src/bmpimage.cpp
@@ -46,10 +46,17 @@ EXIV2_RCSID("@(#) $Id$")
 // class member definitions
 namespace Exiv2 {
 
+#ifdef EXV_USING_CPP_ELEVEN
+    BmpImage::BmpImage(BasicIo::AutoPtr io)
+        : Image(ImageType::bmp, mdNone, std::move(io))
+    {
+    } // BmpImage::BmpImage
+#else
     BmpImage::BmpImage(BasicIo::AutoPtr io)
         : Image(ImageType::bmp, mdNone, io)
     {
     } // BmpImage::BmpImage
+#endif
 
     std::string BmpImage::mimeType() const
     {
@@ -131,7 +138,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newBmpInstance(BasicIo::AutoPtr io, bool /*create*/)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new BmpImage(std::move(io)));
+#else
         Image::AutoPtr image(new BmpImage(io));
+#endif
         if (!image->good())
         {
             image.reset();
diff --git a/src/convert.cpp b/src/convert.cpp
index 26a5fd8b..c6131845 100644
--- a/src/convert.cpp
+++ b/src/convert.cpp
@@ -35,7 +35,7 @@ EXIV2_RCSID("@(#) $Id$")
 #include "types.hpp"
 #include "exif.hpp"
 #include "iptc.hpp"
-#include "xmp.hpp"
+#include "xmp_exiv2.hpp"
 #include "futils.hpp"
 #include "convert.hpp"
 
@@ -63,7 +63,7 @@ EXIV2_RCSID("@(#) $Id$")
 // Adobe XMP Toolkit
 #ifdef EXV_HAVE_XMP_TOOLKIT
 # define TXMP_STRING_TYPE std::string
-# include <XMPSDK.hpp>
+# include <XMP.hpp>
 # include <MD5.h>
 #endif // EXV_HAVE_XMP_TOOLKIT
 
@@ -1182,7 +1182,7 @@ namespace Exiv2 {
         MD5_CTX    context;
         unsigned char digest[16];
 
-        MD5Init ( &context );
+        EXIV2_MD5Init ( &context );
         for (unsigned int i = 0; i < EXV_COUNTOF(conversion_); ++i) {
             const Conversion& c = conversion_[i];
             if (c.metadataId_ == mdExif) {
@@ -1196,10 +1196,10 @@ namespace Exiv2 {
                 if (pos == exifData_->end()) continue;
                 DataBuf data(pos->size());
                 pos->copy(data.pData_, littleEndian /* FIXME ? */);
-                MD5Update ( &context, data.pData_, data.size_);
+                EXIV2_MD5Update ( &context, data.pData_, data.size_);
             }
         }
-        MD5Final(digest, &context);
+        EXIV2_MD5Final(digest, &context);
         res << ';';
         res << std::setw(2) << std::setfill('0') << std::hex << std::uppercase;
         for (int i = 0; i < 16; ++i) {
@@ -1268,11 +1268,11 @@ namespace Exiv2 {
         MD5_CTX context;
         unsigned char digest[16];
 
-        MD5Init(&context);
+        EXIV2_MD5Init(&context);
 
         DataBuf data = IptcParser::encode(*iptcData_);
-        MD5Update(&context, data.pData_, data.size_);
-        MD5Final(digest, &context);
+        EXIV2_MD5Update(&context, data.pData_, data.size_);
+        EXIV2_MD5Final(digest, &context);
         res << std::setw(2) << std::setfill('0') << std::hex << std::uppercase;
         for (int i = 0; i < 16; ++i) {
             res << static_cast<int>(digest[i]);
diff --git a/src/cr2image.cpp b/src/cr2image.cpp
index 2907426c..f02a55f1 100644
--- a/src/cr2image.cpp
+++ b/src/cr2image.cpp
@@ -51,8 +51,13 @@ namespace Exiv2 {
 
     using namespace Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    Cr2Image::Cr2Image(BasicIo::AutoPtr io, bool /*create*/)
+        : Image(ImageType::cr2, mdExif | mdIptc | mdXmp, std::move(io))
+#else
     Cr2Image::Cr2Image(BasicIo::AutoPtr io, bool /*create*/)
         : Image(ImageType::cr2, mdExif | mdIptc | mdXmp, io)
+#endif
     {
     } // Cr2Image::Cr2Image
 
@@ -190,7 +195,11 @@ namespace Exiv2 {
                      ed.end());
         }
 
+#ifdef EXV_USING_CPP_ELEVEN
+        std::unique_ptr<TiffHeaderBase> header(new Cr2Header(byteOrder));
+#else
         std::auto_ptr<TiffHeaderBase> header(new Cr2Header(byteOrder));
+#endif
         OffsetWriter offsetWriter;
         offsetWriter.setOrigin(OffsetWriter::cr2RawIfdOffset, Cr2Header::offset2addr(), byteOrder);
         return TiffParserWorker::encode(io,
@@ -209,7 +218,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newCr2Instance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new Cr2Image(std::move(io), create));
+#else
         Image::AutoPtr image(new Cr2Image(io, create));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/crwimage.cpp b/src/crwimage.cpp
index ca79aa74..6c369587 100644
--- a/src/crwimage.cpp
+++ b/src/crwimage.cpp
@@ -82,8 +82,13 @@ namespace Exiv2 {
 
     using namespace Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    CrwImage::CrwImage(BasicIo::AutoPtr io, bool /*create*/)
+        : Image(ImageType::crw, mdExif | mdComment, std::move(io))
+#else
     CrwImage::CrwImage(BasicIo::AutoPtr io, bool /*create*/)
         : Image(ImageType::crw, mdExif | mdComment, io)
+#endif
     {
     } // CrwImage::CrwImage
 
@@ -222,7 +227,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newCrwInstance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new CrwImage(std::move(io), create));
+#else
         Image::AutoPtr image(new CrwImage(io, create));
+#endif
         if (!image->good()) {
             image.reset();
         }
@@ -360,7 +369,11 @@ namespace Exiv2 {
 
     void CiffComponent::add(AutoPtr component)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        doAdd(std::move(component));
+#else
         doAdd(component);
+#endif
     }
 
     void CiffEntry::doAdd(AutoPtr /*component*/)
@@ -476,7 +489,11 @@ namespace Exiv2 {
             }
             m->setDir(this->tag());
             m->read(pData, size, o, byteOrder);
+#ifdef EXV_USING_CPP_ELEVEN
+            add(std::move(m));
+#else
             add(m);
+#endif
             o += 10;
         }
     }  // CiffDirectory::readDirectory
@@ -848,7 +865,11 @@ namespace Exiv2 {
                 // Directory doesn't exist yet, add it
                 m_ = AutoPtr(new CiffDirectory(csd.crwDir_, csd.parent_));
                 cc_ = m_.get();
+#ifdef EXV_USING_CPP_ELEVEN
+                add(std::move(m_));
+#else
                 add(m_);
+#endif
             }
             // Recursive call to next lower level directory
             cc_ = cc_->add(crwDirs, crwTagId);
@@ -865,7 +886,11 @@ namespace Exiv2 {
                 // Tag doesn't exist yet, add it
                 m_ = AutoPtr(new CiffEntry(crwTagId, tag()));
                 cc_ = m_.get();
+#ifdef EXV_USING_CPP_ELEVEN
+                add(std::move(m_));
+#else
                 add(m_);
+#endif
             }
         }
         return cc_;
diff --git a/src/crwimage_int.hpp b/src/crwimage_int.hpp
index 01a0c572..f14ab348 100644
--- a/src/crwimage_int.hpp
+++ b/src/crwimage_int.hpp
@@ -96,7 +96,11 @@ namespace Exiv2 {
     class CiffComponent {
     public:
         //! CiffComponent auto_ptr type
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<CiffComponent> AutoPtr;
+#else
         typedef std::auto_ptr<CiffComponent> AutoPtr;
+#endif
         //! Container type to hold all metadata
         typedef std::vector<CiffComponent*> Components;
 
@@ -440,7 +444,11 @@ namespace Exiv2 {
     class CiffHeader {
     public:
         //! CiffHeader auto_ptr type
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<CiffHeader> AutoPtr;
+#else
         typedef std::auto_ptr<CiffHeader> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
diff --git a/src/epsimage.cpp b/src/epsimage.cpp
index c50b6382..702f5f2e 100644
--- a/src/epsimage.cpp
+++ b/src/epsimage.cpp
@@ -1079,8 +1079,13 @@ namespace {
 namespace Exiv2
 {
 
+#ifdef EXV_USING_CPP_ELEVEN
+    EpsImage::EpsImage(BasicIo::AutoPtr io, bool create)
+            : Image(ImageType::eps, mdXmp, std::move(io))
+#else
     EpsImage::EpsImage(BasicIo::AutoPtr io, bool create)
             : Image(ImageType::eps, mdXmp, io)
+#endif
     {
         //LogMsg::setLevel(LogMsg::debug);
         if (create) {
@@ -1157,7 +1162,11 @@ namespace Exiv2
     // free functions
     Image::AutoPtr newEpsInstance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new EpsImage(std::move(io), create));
+#else
         Image::AutoPtr image(new EpsImage(io, create));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/exif.cpp b/src/exif.cpp
index 628fa63f..0b53218f 100644
--- a/src/exif.cpp
+++ b/src/exif.cpp
@@ -85,7 +85,11 @@ namespace {
     class Thumbnail {
     public:
         //! Shortcut for a %Thumbnail auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Thumbnail> AutoPtr;
+#else
         typedef std::auto_ptr<Thumbnail> AutoPtr;
+#endif
 
         //! @name Creators
         //@{
@@ -128,7 +132,11 @@ namespace {
     class TiffThumbnail : public Thumbnail {
     public:
         //! Shortcut for a %TiffThumbnail auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<TiffThumbnail> AutoPtr;
+#else
         typedef std::auto_ptr<TiffThumbnail> AutoPtr;
+#endif
 
         //! @name Manipulators
         //@{
@@ -152,7 +160,11 @@ namespace {
     class JpegThumbnail : public Thumbnail {
     public:
         //! Shortcut for a %JpegThumbnail auto pointer.
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<JpegThumbnail> AutoPtr;
+#else
         typedef std::auto_ptr<JpegThumbnail> AutoPtr;
+#endif
 
         //! @name Manipulators
         //@{
@@ -197,10 +209,19 @@ namespace Exiv2 {
     template<typename T>
     Exiv2::Exifdatum& setValue(Exiv2::Exifdatum& exifDatum, const T& value)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        std::unique_ptr<Exiv2::ValueType<T> > v
+            = std::unique_ptr<Exiv2::ValueType<T> >(new Exiv2::ValueType<T>);
+#else
         std::auto_ptr<Exiv2::ValueType<T> > v
             = std::auto_ptr<Exiv2::ValueType<T> >(new Exiv2::ValueType<T>);
+#endif
         v->value_.push_back(value);
+#ifdef EXV_USING_CPP_ELEVEN
+        exifDatum.value_ = std::move(v);
+#else
         exifDatum.value_ = v;
+#endif
         return exifDatum;
     }
 
@@ -414,7 +435,11 @@ namespace Exiv2 {
 
     Value::AutoPtr Exifdatum::getValue() const
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        return value_.get() == 0 ? Value::AutoPtr(nullptr) : value_->clone();
+#else
         return value_.get() == 0 ? Value::AutoPtr(0) : value_->clone();
+#endif
     }
 
     long Exifdatum::sizeDataArea() const
@@ -706,7 +731,11 @@ namespace Exiv2 {
 
         // Encode and check if the result fits into a JPEG Exif APP1 segment
         MemIo mio1;
+#ifdef EXV_USING_CPP_ELEVEN
+        std::unique_ptr<TiffHeaderBase> header(new TiffHeader(byteOrder, 0x00000008, false));
+#else
         std::auto_ptr<TiffHeaderBase> header(new TiffHeader(byteOrder, 0x00000008, false));
+#endif
         WriteMethod wm = TiffParserWorker::encode(mio1,
                                                   pData,
                                                   size,
diff --git a/src/exiv2.cpp b/src/exiv2.cpp
index d6a45e1b..733856e5 100644
--- a/src/exiv2.cpp
+++ b/src/exiv2.cpp
@@ -38,7 +38,7 @@ EXIV2_RCSID("@(#) $Id$")
 #include "utils.hpp"
 #include "convert.hpp"
 #include "i18n.h"      // NLS support.
-#include "xmp.hpp"
+#include "xmp_exiv2.hpp"
 
 #include <iostream>
 #include <fstream>
diff --git a/src/gifimage.cpp b/src/gifimage.cpp
index 67bc9eee..3363505c 100644
--- a/src/gifimage.cpp
+++ b/src/gifimage.cpp
@@ -47,8 +47,13 @@ EXIV2_RCSID("@(#) $Id$")
 // class member definitions
 namespace Exiv2 {
 
+#ifdef EXV_USING_CPP_ELEVEN
+    GifImage::GifImage(BasicIo::AutoPtr io)
+        : Image(ImageType::gif, mdNone, std::move(io))
+#else
     GifImage::GifImage(BasicIo::AutoPtr io)
         : Image(ImageType::gif, mdNone, io)
+#endif
     {
     } // GifImage::GifImage
 
@@ -111,7 +116,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newGifInstance(BasicIo::AutoPtr io, bool /*create*/)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new GifImage(std::move(io)));
+#else
         Image::AutoPtr image(new GifImage(io));
+#endif
         if (!image->good())
         {
             image.reset();
diff --git a/src/image.cpp b/src/image.cpp
index 0db66eb0..9db32edc 100644
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -152,7 +152,11 @@ namespace Exiv2 {
     Image::Image(int              imageType,
                  uint16_t         supportedMetadata,
                  BasicIo::AutoPtr io)
+#ifdef EXV_USING_CPP_ELEVEN
+        : io_(std::move(io)),
+#else
         : io_(io),
+#endif
           pixelWidth_(0),
           pixelHeight_(0),
           imageType_(imageType),
@@ -862,7 +866,11 @@ namespace Exiv2 {
     Image::AutoPtr ImageFactory::open(const byte* data, long size)
     {
         BasicIo::AutoPtr io(new MemIo(data, size));
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image = open(std::move(io)); // may throw
+#else
         Image::AutoPtr image = open(io); // may throw
+#endif
         if (image.get() == 0) throw Error(12);
         return image;
     }
@@ -874,7 +882,11 @@ namespace Exiv2 {
         }
         for (unsigned int i = 0; registry[i].imageType_ != ImageType::none; ++i) {
             if (registry[i].isThisType_(*io, false)) {
+#ifdef EXV_USING_CPP_ELEVEN
+                return registry[i].newInstance_(std::move(io), false);
+#else
                 return registry[i].newInstance_(io, false);
+#endif
             }
         }
         return Image::AutoPtr();
@@ -883,14 +895,23 @@ namespace Exiv2 {
     Image::AutoPtr ImageFactory::create(int type,
                                         const std::string& path)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        std::unique_ptr<FileIo> fileIo(new FileIo(path));
+#else
         std::auto_ptr<FileIo> fileIo(new FileIo(path));
+#endif
         // Create or overwrite the file, then close it
         if (fileIo->open("w+b") != 0) {
             throw Error(10, path, "w+b", strError());
         }
         fileIo->close();
+#ifdef EXV_USING_CPP_ELEVEN
+        BasicIo::AutoPtr io(std::move(fileIo));
+        Image::AutoPtr image = create(type, std::move(io));
+#else
         BasicIo::AutoPtr io(fileIo);
         Image::AutoPtr image = create(type, io);
+#endif
         if (image.get() == 0) throw Error(13, type);
         return image;
     }
@@ -899,14 +920,23 @@ namespace Exiv2 {
     Image::AutoPtr ImageFactory::create(int type,
                                         const std::wstring& wpath)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        std::unique_ptr<FileIo> fileIo(new FileIo(wpath));
+#else
         std::auto_ptr<FileIo> fileIo(new FileIo(wpath));
+#endif
         // Create or overwrite the file, then close it
         if (fileIo->open("w+b") != 0) {
             throw WError(10, wpath, "w+b", strError().c_str());
         }
         fileIo->close();
+#ifdef EXV_USING_CPP_ELEVEN
+        BasicIo::AutoPtr io(std::move(fileIo));
+        Image::AutoPtr image = create(type, std::move(io));
+#else
         BasicIo::AutoPtr io(fileIo);
         Image::AutoPtr image = create(type, io);
+#endif
         if (image.get() == 0) throw Error(13, type);
         return image;
     }
@@ -915,7 +945,11 @@ namespace Exiv2 {
     Image::AutoPtr ImageFactory::create(int type)
     {
         BasicIo::AutoPtr io(new MemIo);
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image = create(type, std::move(io));
+#else
         Image::AutoPtr image = create(type, io);
+#endif
         if (image.get() == 0) throw Error(13, type);
         return image;
     }
@@ -926,7 +960,11 @@ namespace Exiv2 {
         // BasicIo instance does not need to be open
         const Registry* r = find(registry, type);
         if (0 != r) {
+#ifdef EXV_USING_CPP_ELEVEN
+            return r->newInstance_(std::move(io), true);
+#else
             return r->newInstance_(io, true);
+#endif
         }
         return Image::AutoPtr();
     } // ImageFactory::create
diff --git a/src/iptc.cpp b/src/iptc.cpp
index 99f5ee5b..cb25d78f 100644
--- a/src/iptc.cpp
+++ b/src/iptc.cpp
@@ -210,7 +210,11 @@ namespace Exiv2 {
 
     Value::AutoPtr Iptcdatum::getValue() const
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        return value_.get() == 0 ? Value::AutoPtr(nullptr) : value_->clone();
+#else
         return value_.get() == 0 ? Value::AutoPtr(0) : value_->clone();
+#endif
     }
 
     const Value& Iptcdatum::value() const
@@ -237,7 +241,11 @@ namespace Exiv2 {
     {
         UShortValue::AutoPtr v(new UShortValue);
         v->value_.push_back(value);
+#ifdef EXV_USING_CPP_ELEVEN
+        value_ = std::move(v);
+#else
         value_ = v;
+#endif
         return *this;
     }
 
diff --git a/src/jp2image.cpp b/src/jp2image.cpp
index 1892fd43..5c7169f8 100644
--- a/src/jp2image.cpp
+++ b/src/jp2image.cpp
@@ -141,8 +141,13 @@ struct Jp2UuidBox
 namespace Exiv2
 {
 
+#ifdef EXV_USING_CPP_ELEVEN
+    Jp2Image::Jp2Image(BasicIo::AutoPtr io, bool create)
+            : Image(ImageType::jp2, mdExif | mdIptc | mdXmp, std::move(io))
+#else
     Jp2Image::Jp2Image(BasicIo::AutoPtr io, bool create)
             : Image(ImageType::jp2, mdExif | mdIptc | mdXmp, io)
+#endif
     {
         if (create)
         {
@@ -911,7 +916,11 @@ namespace Exiv2
     // free functions
     Image::AutoPtr newJp2Instance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new Jp2Image(std::move(io), create));
+#else
         Image::AutoPtr image(new Jp2Image(io, create));
+#endif
         if (!image->good())
         {
             image.reset();
diff --git a/src/jpgimage.cpp b/src/jpgimage.cpp
index 9afcb58b..a8cc5786 100644
--- a/src/jpgimage.cpp
+++ b/src/jpgimage.cpp
@@ -302,9 +302,15 @@ namespace Exiv2 {
 
     } // Photoshop::setIptcIrb
 
+#ifdef EXV_USING_CPP_ELEVEN
+    JpegBase::JpegBase(int type, BasicIo::AutoPtr io, bool create,
+                       const byte initData[], long dataSize)
+        : Image(type, mdExif | mdIptc | mdXmp | mdComment, std::move(io))
+#else
     JpegBase::JpegBase(int type, BasicIo::AutoPtr io, bool create,
                        const byte initData[], long dataSize)
         : Image(type, mdExif | mdIptc | mdXmp | mdComment, io)
+#endif
     {
         if (create) {
             initImage(initData, dataSize);
@@ -1237,8 +1243,13 @@ namespace Exiv2 {
         0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0xDA,0x00,0x0C,0x03,0x01,0x00,0x02,
         0x11,0x03,0x11,0x00,0x3F,0x00,0xA0,0x00,0x0F,0xFF,0xD9 };
 
+#ifdef EXV_USING_CPP_ELEVEN
+    JpegImage::JpegImage(BasicIo::AutoPtr io, bool create)
+        : JpegBase(ImageType::jpeg, std::move(io), create, blank_, sizeof(blank_))
+#else
     JpegImage::JpegImage(BasicIo::AutoPtr io, bool create)
         : JpegBase(ImageType::jpeg, io, create, blank_, sizeof(blank_))
+#endif
     {
     }
 
@@ -1265,7 +1276,11 @@ namespace Exiv2 {
 
     Image::AutoPtr newJpegInstance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new JpegImage(std::move(io), create));
+#else
         Image::AutoPtr image(new JpegImage(io, create));
+#endif
         if (!image->good()) {
             image.reset();
         }
@@ -1289,8 +1304,13 @@ namespace Exiv2 {
     const char ExvImage::exiv2Id_[] = "Exiv2";
     const byte ExvImage::blank_[] = { 0xff,0x01,'E','x','i','v','2',0xff,0xd9 };
 
+#ifdef EXV_USING_CPP_ELEVEN
+    ExvImage::ExvImage(BasicIo::AutoPtr io, bool create)
+        : JpegBase(ImageType::exv, std::move(io), create, blank_, sizeof(blank_))
+#else
     ExvImage::ExvImage(BasicIo::AutoPtr io, bool create)
         : JpegBase(ImageType::exv, io, create, blank_, sizeof(blank_))
+#endif
     {
     }
 
@@ -1319,7 +1339,11 @@ namespace Exiv2 {
     Image::AutoPtr newExvInstance(BasicIo::AutoPtr io, bool create)
     {
         Image::AutoPtr image;
+#ifdef EXV_USING_CPP_ELEVEN
+        image = Image::AutoPtr(new ExvImage(std::move(io), create));
+#else
         image = Image::AutoPtr(new ExvImage(io, create));
+#endif
         if (!image->good()) image.reset();
         return image;
     }
diff --git a/src/matroskavideo.cpp b/src/matroskavideo.cpp
index 0e4cf004..7a3ee4b7 100644
--- a/src/matroskavideo.cpp
+++ b/src/matroskavideo.cpp
@@ -482,8 +482,13 @@ namespace Exiv2 {
 
     using namespace Exiv2::Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    MatroskaVideo::MatroskaVideo(BasicIo::AutoPtr io)
+        : Image(ImageType::mkv, mdNone, std::move(io))
+#else
     MatroskaVideo::MatroskaVideo(BasicIo::AutoPtr io)
         : Image(ImageType::mkv, mdNone, io)
+#endif
     {
     } // MatroskaVideo::MatroskaVideo
 
@@ -743,7 +748,11 @@ namespace Exiv2 {
 
     Image::AutoPtr newMkvInstance(BasicIo::AutoPtr io, bool /*create*/)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new MatroskaVideo(std::move(io)));
+#else
         Image::AutoPtr image(new MatroskaVideo(io));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/mrwimage.cpp b/src/mrwimage.cpp
index 611a739f..938428be 100644
--- a/src/mrwimage.cpp
+++ b/src/mrwimage.cpp
@@ -49,8 +49,13 @@ EXIV2_RCSID("@(#) $Id$")
 // class member definitions
 namespace Exiv2 {
 
+#ifdef EXV_USING_CPP_ELEVEN
+    MrwImage::MrwImage(BasicIo::AutoPtr io, bool /*create*/)
+        : Image(ImageType::mrw, mdExif | mdIptc | mdXmp, std::move(io))
+#else
     MrwImage::MrwImage(BasicIo::AutoPtr io, bool /*create*/)
         : Image(ImageType::mrw, mdExif | mdIptc | mdXmp, io)
+#endif
     {
     } // MrwImage::MrwImage
 
@@ -158,7 +163,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newMrwInstance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new MrwImage(std::move(io), create));
+#else
         Image::AutoPtr image(new MrwImage(io, create));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/orfimage.cpp b/src/orfimage.cpp
index c5165911..48f4b705 100644
--- a/src/orfimage.cpp
+++ b/src/orfimage.cpp
@@ -54,8 +54,13 @@ namespace Exiv2 {
 
     using namespace Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    OrfImage::OrfImage(BasicIo::AutoPtr io, bool create)
+        : TiffImage(/*ImageType::orf, mdExif | mdIptc | mdXmp,*/ std::move(io),create)
+#else
     OrfImage::OrfImage(BasicIo::AutoPtr io, bool create)
         : TiffImage(/*ImageType::orf, mdExif | mdIptc | mdXmp,*/ io,create)
+#endif
     {
     	setTypeSupported(ImageType::orf, mdExif | mdIptc | mdXmp);
     } // OrfImage::OrfImage
@@ -202,7 +207,11 @@ namespace Exiv2 {
                      ed.end());
         }
 
+#ifdef EXV_USING_CPP_ELEVEN
+        std::unique_ptr<TiffHeaderBase> header(new OrfHeader(byteOrder));
+#else
         std::auto_ptr<TiffHeaderBase> header(new OrfHeader(byteOrder));
+#endif
         return TiffParserWorker::encode(io,
                                         pData,
                                         size,
@@ -219,7 +228,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newOrfInstance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new OrfImage(std::move(io), create));
+#else
         Image::AutoPtr image(new OrfImage(io, create));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/pgfimage.cpp b/src/pgfimage.cpp
index 82706d11..64e0144f 100644
--- a/src/pgfimage.cpp
+++ b/src/pgfimage.cpp
@@ -86,9 +86,15 @@ namespace Exiv2 {
         return result;
     }
 
+#ifdef EXV_USING_CPP_ELEVEN
+    PgfImage::PgfImage(BasicIo::AutoPtr io, bool create)
+            : Image(ImageType::pgf, mdExif | mdIptc| mdXmp | mdComment, std::move(io))
+            , bSwap_(isBigEndianPlatform())
+#else
     PgfImage::PgfImage(BasicIo::AutoPtr io, bool create)
             : Image(ImageType::pgf, mdExif | mdIptc| mdXmp | mdComment, io)
             , bSwap_(isBigEndianPlatform())
+#endif
     {
         if (create)
         {
@@ -321,7 +327,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newPgfInstance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new PgfImage(std::move(io), create));
+#else
         Image::AutoPtr image(new PgfImage(io, create));
+#endif
         if (!image->good())
         {
             image.reset();
diff --git a/src/pngchunk.cpp b/src/pngchunk.cpp
index da4ccd01..16e54aa7 100644
--- a/src/pngchunk.cpp
+++ b/src/pngchunk.cpp
@@ -586,8 +586,13 @@ namespace Exiv2 {
     DataBuf PngChunk::readRawProfile(const DataBuf& text,bool iTXt)
     {
         DataBuf                 info;
+#ifdef EXV_USING_CPP_ELEVEN
+        long           i;
+        unsigned char *dp;
+#else
         register long           i;
         register unsigned char *dp;
+#endif
         const char             *sp;
         unsigned int            nibbles;
         long                    length;
diff --git a/src/pngimage.cpp b/src/pngimage.cpp
index 11b41982..8163ffa7 100644
--- a/src/pngimage.cpp
+++ b/src/pngimage.cpp
@@ -69,8 +69,13 @@ namespace Exiv2 {
 
     using namespace Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    PngImage::PngImage(BasicIo::AutoPtr io, bool create)
+            : Image(ImageType::png, mdExif | mdIptc | mdXmp | mdComment, std::move(io))
+#else
     PngImage::PngImage(BasicIo::AutoPtr io, bool create)
             : Image(ImageType::png, mdExif | mdIptc | mdXmp | mdComment, io)
+#endif
     {
         if (create)
         {
@@ -707,7 +712,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newPngInstance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new PngImage(std::move(io), create));
+#else
         Image::AutoPtr image(new PngImage(io, create));
+#endif
         if (!image->good())
         {
             image.reset();
diff --git a/src/preview.cpp b/src/preview.cpp
index c34c8bd2..7f54b7a6 100644
--- a/src/preview.cpp
+++ b/src/preview.cpp
@@ -95,7 +95,11 @@ namespace {
         virtual ~Loader() {}
 
         //! Loader auto pointer
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<Loader> AutoPtr;
+#else
         typedef std::auto_ptr<Loader> AutoPtr;
+#endif
 
         //! Create a Loader subclass for requested id
         static AutoPtr create(PreviewId id, const Image &image);
diff --git a/src/properties.cpp b/src/properties.cpp
index 01273823..05d421c0 100644
--- a/src/properties.cpp
+++ b/src/properties.cpp
@@ -38,7 +38,7 @@ EXIV2_RCSID("@(#) $Id$")
 #include "value.hpp"
 #include "metadatum.hpp"
 #include "i18n.h"                // NLS support.
-#include "xmp.hpp"
+#include "xmp_exiv2.hpp"
 #include "rwlock.hpp"
 
 #include <iostream>
@@ -129,10 +129,12 @@ namespace Exiv2 {
         { "http://ns.adobe.com/exif/1.0/",                "exif",           xmpExifInfo,      N_("Exif schema for Exif-specific Properties")  },
         { "http://cipa.jp/exif/1.0/",                     "exifEX",         xmpExifEXInfo,    N_("Exif 2.3 metadata for XMP")  },
         { "http://ns.adobe.com/exif/1.0/aux/",            "aux",            xmpAuxInfo,       N_("Exif schema for Additional Exif Properties")},
+#if 0
         { "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/",  "iptc",           xmpIptcInfo,      N_("IPTC Core schema")                          }, // NOTE: 'Iptc4xmpCore' is just too long, so make 'iptc'
         { "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/",  "Iptc4xmpCore",   xmpIptcInfo,      N_("IPTC Core schema")                          }, // the default prefix. But provide the official one too.
         { "http://iptc.org/std/Iptc4xmpExt/2008-02-29/",  "iptcExt",        xmpIptcExtInfo,   N_("IPTC Extension schema")                     }, // NOTE: It really should be 'Iptc4xmpExt' but following
         { "http://iptc.org/std/Iptc4xmpExt/2008-02-29/",  "Iptc4xmpExt",    xmpIptcExtInfo,   N_("IPTC Extension schema")                     }, // example above, 'iptcExt' is the default, Iptc4xmpExt works too.
+#endif
         { "http://ns.useplus.org/ldf/xmp/1.0/",           "plus",           xmpPlusInfo,      N_("PLUS License Data Format schema")           },
         { "http://ns.iview-multimedia.com/mediapro/1.0/", "mediapro",       xmpMediaProInfo,  N_("iView Media Pro schema")                    },
         { "http://ns.microsoft.com/expressionmedia/1.0/", "expressionmedia", xmpExpressionMediaInfo, N_("Expression Media schema")            },
diff --git a/src/psdimage.cpp b/src/psdimage.cpp
index 5f721c70..3a04afe1 100644
--- a/src/psdimage.cpp
+++ b/src/psdimage.cpp
@@ -125,8 +125,13 @@ enum {
 // class member definitions
 namespace Exiv2 {
 
+#ifdef EXV_USING_CPP_ELEVEN
+    PsdImage::PsdImage(BasicIo::AutoPtr io)
+        : Image(ImageType::psd, mdExif | mdIptc | mdXmp, std::move(io))
+#else
     PsdImage::PsdImage(BasicIo::AutoPtr io)
         : Image(ImageType::psd, mdExif | mdIptc | mdXmp, io)
+#endif
     {
     } // PsdImage::PsdImage
 
@@ -683,7 +688,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newPsdInstance(BasicIo::AutoPtr io, bool /*create*/)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new PsdImage(std::move(io)));
+#else
         Image::AutoPtr image(new PsdImage(io));
+#endif
         if (!image->good())
         {
             image.reset();
diff --git a/src/quicktimevideo.cpp b/src/quicktimevideo.cpp
index 8b30d173..e377c994 100644
--- a/src/quicktimevideo.cpp
+++ b/src/quicktimevideo.cpp
@@ -611,9 +611,15 @@ namespace Exiv2 {
 
     using namespace Exiv2::Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    QuickTimeVideo::QuickTimeVideo(BasicIo::AutoPtr io)
+            : Image(ImageType::qtime, mdNone, std::move(io))
+            , timeScale_(1)
+#else
     QuickTimeVideo::QuickTimeVideo(BasicIo::AutoPtr io)
             : Image(ImageType::qtime, mdNone, io)
             , timeScale_(1)
+#endif
     {
     } // QuickTimeVideo::QuickTimeVideo
 
@@ -1632,7 +1638,11 @@ namespace Exiv2 {
 
 
     Image::AutoPtr newQTimeInstance(BasicIo::AutoPtr io, bool /*create*/) {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new QuickTimeVideo(std::move(io)));
+#else
         Image::AutoPtr image(new QuickTimeVideo(io));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/rafimage.cpp b/src/rafimage.cpp
index 65742a35..846db503 100644
--- a/src/rafimage.cpp
+++ b/src/rafimage.cpp
@@ -50,8 +50,13 @@ EXIV2_RCSID("@(#) $Id$")
 // class member definitions
 namespace Exiv2 {
 
+#ifdef EXV_USING_CPP_ELEVEN
+    RafImage::RafImage(BasicIo::AutoPtr io, bool /*create*/)
+        : Image(ImageType::raf, mdExif | mdIptc | mdXmp, std::move(io))
+#else
     RafImage::RafImage(BasicIo::AutoPtr io, bool /*create*/)
         : Image(ImageType::raf, mdExif | mdIptc | mdXmp, io)
+#endif
     {
     } // RafImage::RafImage
 
@@ -331,7 +336,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newRafInstance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new RafImage(std::move(io), create));
+#else
         Image::AutoPtr image(new RafImage(io, create));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/riffvideo.cpp b/src/riffvideo.cpp
index 1edbbe56..c413c661 100644
--- a/src/riffvideo.cpp
+++ b/src/riffvideo.cpp
@@ -507,8 +507,13 @@ namespace Exiv2 {
 namespace Exiv2 {
     using namespace Exiv2::Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    RiffVideo::RiffVideo(BasicIo::AutoPtr io)
+            : Image(ImageType::riff, mdNone, std::move(io))
+#else
     RiffVideo::RiffVideo(BasicIo::AutoPtr io)
             : Image(ImageType::riff, mdNone, io)
+#endif
     {
     } // RiffVideo::RiffVideo
 
@@ -1311,7 +1316,11 @@ namespace Exiv2 {
 
     Image::AutoPtr newRiffInstance(BasicIo::AutoPtr io, bool /*create*/)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new RiffVideo(std::move(io)));
+#else
         Image::AutoPtr image(new RiffVideo(io));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/rw2image.cpp b/src/rw2image.cpp
index 95f3b28e..81ee1cef 100644
--- a/src/rw2image.cpp
+++ b/src/rw2image.cpp
@@ -52,8 +52,13 @@ namespace Exiv2 {
 
     using namespace Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    Rw2Image::Rw2Image(BasicIo::AutoPtr io)
+        : Image(ImageType::rw2, mdExif | mdIptc | mdXmp, std::move(io))
+#else
     Rw2Image::Rw2Image(BasicIo::AutoPtr io)
         : Image(ImageType::rw2, mdExif | mdIptc | mdXmp, io)
+#endif
     {
     } // Rw2Image::Rw2Image
 
@@ -253,7 +258,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newRw2Instance(BasicIo::AutoPtr io, bool /*create*/)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new Rw2Image(std::move(io)));
+#else
         Image::AutoPtr image(new Rw2Image(io));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/tgaimage.cpp b/src/tgaimage.cpp
index c4c33499..0f389ce6 100644
--- a/src/tgaimage.cpp
+++ b/src/tgaimage.cpp
@@ -46,8 +46,13 @@ EXIV2_RCSID("@(#) $Id$")
 // class member definitions
 namespace Exiv2 {
 
+#ifdef EXV_USING_CPP_ELEVEN
+    TgaImage::TgaImage(BasicIo::AutoPtr io)
+        : Image(ImageType::tga, mdNone, std::move(io))
+#else
     TgaImage::TgaImage(BasicIo::AutoPtr io)
         : Image(ImageType::tga, mdNone, io)
+#endif
     {
     } // TgaImage::TgaImage
 
@@ -132,7 +137,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newTgaInstance(BasicIo::AutoPtr io, bool /*create*/)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new TgaImage(std::move(io)));
+#else
         Image::AutoPtr image(new TgaImage(io));
+#endif
         if (!image->good())
         {
             image.reset();
diff --git a/src/tiffcomposite.cpp b/src/tiffcomposite.cpp
index 0c9b9c4a..b172bd57 100644
--- a/src/tiffcomposite.cpp
+++ b/src/tiffcomposite.cpp
@@ -387,7 +387,11 @@ namespace Exiv2 {
         memset(pData_, 0x0, size_);
         size_ = value->copy(pData_, byteOrder);
         assert(size_ == newSize);
+#ifdef EXV_USING_CPP_ELEVEN
+        setValue(std::move(value));
+#else
         setValue(value);
+#endif
     } // TiffEntryBase::updateValue
 
     void TiffEntryBase::setValue(Value::AutoPtr value)
@@ -626,7 +630,11 @@ namespace Exiv2 {
         tp->setData(const_cast<byte*>(pData() + idx), sz);
         tp->setElDef(def);
         tp->setElByteOrder(cfg()->byteOrder_);
+#ifdef EXV_USING_CPP_ELEVEN
+        addChild(std::move(tc));
+#else
         addChild(tc);
+#endif
         return sz;
     } // TiffBinaryArray::addElement
 
@@ -635,7 +643,11 @@ namespace Exiv2 {
                                           TiffComponent* const pRoot,
                                           TiffComponent::AutoPtr object)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        return doAddPath(tag, tiffPath, pRoot, std::move(object));
+#else
         return doAddPath(tag, tiffPath, pRoot, object);
+#endif
     } // TiffComponent::addPath
 
     TiffComponent* TiffComponent::doAddPath(uint16_t  /*tag*/,
@@ -677,7 +689,11 @@ namespace Exiv2 {
         if (tc == 0) {
             TiffComponent::AutoPtr atc;
             if (tiffPath.size() == 1 && object.get() != 0) {
+#ifdef EXV_USING_CPP_ELEVEN
+                atc = std::move(object);
+#else
                 atc = object;
+#endif
             }
             else {
                 atc = TiffCreator::create(tpi.extendedTag(), tpi.group());
@@ -689,13 +705,25 @@ namespace Exiv2 {
             if (tiffPath.size() == 1 && dynamic_cast<TiffSubIfd*>(atc.get()) != 0) return 0;
 
             if (tpi.extendedTag() == Tag::next) {
+#ifdef EXV_USING_CPP_ELEVEN
+                tc = this->addNext(std::move(atc));
+#else
                 tc = this->addNext(atc);
+#endif
             }
             else {
+#ifdef EXV_USING_CPP_ELEVEN
+                tc = this->addChild(std::move(atc));
+#else
                 tc = this->addChild(atc);
+#endif
             }
         }
+#ifdef EXV_USING_CPP_ELEVEN
+        return tc->addPath(tag, tiffPath, pRoot, std::move(object));
+#else
         return tc->addPath(tag, tiffPath, pRoot, object);
+#endif
     } // TiffDirectory::doAddPath
 
     TiffComponent* TiffSubIfd::doAddPath(uint16_t tag,
@@ -722,15 +750,27 @@ namespace Exiv2 {
         }
         if (tc == 0) {
             if (tiffPath.size() == 1 && object.get() != 0) {
+#ifdef EXV_USING_CPP_ELEVEN
+                tc = addChild(std::move(object));
+#else
                 tc = addChild(object);
+#endif
             }
             else {
                 TiffComponent::AutoPtr atc(new TiffDirectory(tpi1.tag(), tpi2.group()));
+#ifdef EXV_USING_CPP_ELEVEN
+                tc = addChild(std::move(atc));
+#else
                 tc = addChild(atc);
+#endif
             }
             setCount(static_cast<uint32_t>(ifds_.size()));
         }
+#ifdef EXV_USING_CPP_ELEVEN
+        return tc->addPath(tag, tiffPath, pRoot, std::move(object));
+#else
         return tc->addPath(tag, tiffPath, pRoot, object);
+#endif
     } // TiffSubIfd::doAddPath
 
     TiffComponent* TiffMnEntry::doAddPath(uint16_t tag,
@@ -752,7 +792,11 @@ namespace Exiv2 {
             mn_ = TiffMnCreator::create(tpi1.tag(), tpi1.group(), mnGroup_);
             assert(mn_);
         }
+#ifdef EXV_USING_CPP_ELEVEN
+        return mn_->addPath(tag, tiffPath, pRoot, std::move(object));
+#else
         return mn_->addPath(tag, tiffPath, pRoot, object);
+#endif
     } // TiffMnEntry::doAddPath
 
     TiffComponent* TiffIfdMakernote::doAddPath(uint16_t tag,
@@ -760,7 +804,11 @@ namespace Exiv2 {
                                                TiffComponent* const pRoot,
                                                TiffComponent::AutoPtr object)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        return ifd_.addPath(tag, tiffPath, pRoot, std::move(object));
+#else
         return ifd_.addPath(tag, tiffPath, pRoot, object);
+#endif
     }
 
     TiffComponent* TiffBinaryArray::doAddPath(uint16_t tag,
@@ -792,22 +840,38 @@ namespace Exiv2 {
         if (tc == 0) {
             TiffComponent::AutoPtr atc;
             if (tiffPath.size() == 1 && object.get() != 0) {
+#ifdef EXV_USING_CPP_ELEVEN
+                atc = std::move(object);
+#else
                 atc = object;
+#endif
             }
             else {
                 atc = TiffCreator::create(tpi.extendedTag(), tpi.group());
             }
             assert(atc.get() != 0);
             assert(tpi.extendedTag() != Tag::next);
+#ifdef EXV_USING_CPP_ELEVEN
+            tc = addChild(std::move(atc));
+#else
             tc = addChild(atc);
+#endif
             setCount(static_cast<uint32_t>(elements_.size()));
         }
+#ifdef EXV_USING_CPP_ELEVEN
+        return tc->addPath(tag, tiffPath, pRoot, std::move(object));
+#else
         return tc->addPath(tag, tiffPath, pRoot, object);
+#endif
     } // TiffBinaryArray::doAddPath
 
     TiffComponent* TiffComponent::addChild(TiffComponent::AutoPtr tiffComponent)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        return doAddChild(std::move(tiffComponent));
+#else
         return doAddChild(tiffComponent);
+#endif
     } // TiffComponent::addChild
 
     TiffComponent* TiffComponent::doAddChild(AutoPtr /*tiffComponent*/)
@@ -834,14 +898,22 @@ namespace Exiv2 {
     {
         TiffComponent* tc = 0;
         if (mn_) {
+#ifdef EXV_USING_CPP_ELEVEN
+            tc =  mn_->addChild(std::move(tiffComponent));
+#else
             tc =  mn_->addChild(tiffComponent);
+#endif
         }
         return tc;
     } // TiffMnEntry::doAddChild
 
     TiffComponent* TiffIfdMakernote::doAddChild(TiffComponent::AutoPtr tiffComponent)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        return ifd_.addChild(std::move(tiffComponent));
+#else
         return ifd_.addChild(tiffComponent);
+#endif
     }
 
     TiffComponent* TiffBinaryArray::doAddChild(TiffComponent::AutoPtr tiffComponent)
@@ -854,7 +926,11 @@ namespace Exiv2 {
 
     TiffComponent* TiffComponent::addNext(TiffComponent::AutoPtr tiffComponent)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        return doAddNext(std::move(tiffComponent));
+#else
         return doAddNext(tiffComponent);
+#endif
     } // TiffComponent::addNext
 
     TiffComponent* TiffComponent::doAddNext(AutoPtr /*tiffComponent*/)
@@ -876,14 +952,22 @@ namespace Exiv2 {
     {
         TiffComponent* tc = 0;
         if (mn_) {
+#ifdef EXV_USING_CPP_ELEVEN
+            tc = mn_->addNext(std::move(tiffComponent));
+#else
             tc = mn_->addNext(tiffComponent);
+#endif
         }
         return tc;
     } // TiffMnEntry::doAddNext
 
     TiffComponent* TiffIfdMakernote::doAddNext(TiffComponent::AutoPtr tiffComponent)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        return ifd_.addNext(std::move(tiffComponent));
+#else
         return ifd_.addNext(tiffComponent);
+#endif
     }
 
     void TiffComponent::accept(TiffVisitor& visitor)
diff --git a/src/tiffcomposite_int.hpp b/src/tiffcomposite_int.hpp
index c1256609..db12dfd1 100644
--- a/src/tiffcomposite_int.hpp
+++ b/src/tiffcomposite_int.hpp
@@ -176,7 +176,11 @@ namespace Exiv2 {
     class TiffComponent {
     public:
         //! TiffComponent auto_ptr type
+#ifdef EXV_USING_CPP_ELEVEN
+        typedef std::unique_ptr<TiffComponent> AutoPtr;
+#else
         typedef std::auto_ptr<TiffComponent> AutoPtr;
+#endif
         //! Container type to hold all metadata
         typedef std::vector<TiffComponent*> Components;
 
@@ -202,10 +206,17 @@ namespace Exiv2 {
 
           @return A pointer to the newly added TIFF entry.
          */
+#ifdef EXV_USING_CPP_ELEVEN
+        TiffComponent* addPath(uint16_t tag,
+                               TiffPath& tiffPath,
+                               TiffComponent* const pRoot,
+                               AutoPtr object = AutoPtr(nullptr));
+#else
         TiffComponent* addPath(uint16_t tag,
                                TiffPath& tiffPath,
                                TiffComponent* const pRoot,
                                AutoPtr object =AutoPtr(0));
+#endif
         /*!
           @brief Add a child to the component. Default is to do nothing.
           @param tiffComponent Auto pointer to the component to add.
diff --git a/src/tifffwd_int.hpp b/src/tifffwd_int.hpp
index b4c909d0..ef69d513 100644
--- a/src/tifffwd_int.hpp
+++ b/src/tifffwd_int.hpp
@@ -107,7 +107,11 @@ namespace Exiv2 {
              Use TiffComponent::AutoPtr, it is not used in this declaration only
              to reduce dependencies.
      */
+#ifdef EXV_USING_CPP_ELEVEN
+    typedef std::unique_ptr<TiffComponent> (*NewTiffCompFct)(uint16_t tag, IfdId group);
+#else
     typedef std::auto_ptr<TiffComponent> (*NewTiffCompFct)(uint16_t tag, IfdId group);
+#endif
 
     //! Stack to hold a path from the TIFF root element to a TIFF entry
     typedef std::stack<TiffPathItem> TiffPath;
diff --git a/src/tiffimage.cpp b/src/tiffimage.cpp
index f20c69eb..abc99f55 100644
--- a/src/tiffimage.cpp
+++ b/src/tiffimage.cpp
@@ -75,9 +75,15 @@ namespace Exiv2 {
 
     using namespace Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    TiffImage::TiffImage(BasicIo::AutoPtr io, bool /*create*/)
+        : Image(ImageType::tiff, mdExif | mdIptc | mdXmp, std::move(io)),
+          pixelWidth_(0), pixelHeight_(0)
+#else
     TiffImage::TiffImage(BasicIo::AutoPtr io, bool /*create*/)
         : Image(ImageType::tiff, mdExif | mdIptc | mdXmp, io),
           pixelWidth_(0), pixelHeight_(0)
+#endif
     {
     } // TiffImage::TiffImage
 
@@ -293,7 +299,11 @@ namespace Exiv2 {
                      ed.end());
         }
 
+#ifdef EXV_USING_CPP_ELEVEN
+        std::unique_ptr<TiffHeaderBase> header(new TiffHeader(byteOrder));
+#else
         std::auto_ptr<TiffHeaderBase> header(new TiffHeader(byteOrder));
+#endif
         return TiffParserWorker::encode(io,
                                         pData,
                                         size,
@@ -310,7 +320,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newTiffInstance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new TiffImage(std::move(io), create));
+#else
         Image::AutoPtr image(new TiffImage(io, create));
+#endif
         if (!image->good()) {
             image.reset();
         }
@@ -1841,7 +1855,11 @@ namespace Exiv2 {
     TiffComponent::AutoPtr TiffCreator::create(uint32_t extendedTag,
                                                IfdId    group)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        TiffComponent::AutoPtr tc(nullptr);
+#else
         TiffComponent::AutoPtr tc(0);
+#endif
         uint16_t tag = static_cast<uint16_t>(extendedTag & 0xffff);
         const TiffGroupStruct* ts = find(tiffGroupStruct_,
                                          TiffGroupStruct::Key(extendedTag, group));
@@ -1892,9 +1910,17 @@ namespace Exiv2 {
     )
     {
         // Create standard TIFF header if necessary
+#ifdef EXV_USING_CPP_ELEVEN
+        std::unique_ptr<TiffHeaderBase> ph;
+#else
         std::auto_ptr<TiffHeaderBase> ph;
+#endif
         if (!pHeader) {
+#ifdef EXV_USING_CPP_ELEVEN
+            ph = std::unique_ptr<TiffHeaderBase>(new TiffHeader);
+#else
             ph = std::auto_ptr<TiffHeaderBase>(new TiffHeader);
+#endif
             pHeader = ph.get();
         }
         TiffComponent::AutoPtr rootDir = parse(pData, size, root, pHeader);
@@ -1999,7 +2025,11 @@ namespace Exiv2 {
               TiffHeaderBase*    pHeader
     )
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        if (pData == 0 || size == 0) return TiffComponent::AutoPtr(nullptr);
+#else
         if (pData == 0 || size == 0) return TiffComponent::AutoPtr(0);
+#endif
         if (!pHeader->read(pData, size) || pHeader->offset() >= size) {
             throw Error(3, "TIFF");
         }
diff --git a/src/tiffimage_int.hpp b/src/tiffimage_int.hpp
index aca1ed26..f19af38e 100644
--- a/src/tiffimage_int.hpp
+++ b/src/tiffimage_int.hpp
@@ -258,8 +258,13 @@ namespace Exiv2 {
                  component creation function. If the pointer that is returned
                  is 0, then the TIFF entry should be ignored.
         */
+#ifdef EXV_USING_CPP_ELEVEN
+        static std::unique_ptr<TiffComponent> create(uint32_t extendedTag,
+                                                   IfdId    group);
+#else
         static std::auto_ptr<TiffComponent> create(uint32_t extendedTag,
                                                    IfdId    group);
+#endif
         /*!
           @brief Get the path, i.e., a list of extended tag and group pairs, from
                  the \em root TIFF element to the TIFF entry \em extendedTag and
@@ -351,12 +356,21 @@ namespace Exiv2 {
                            composite structure. If \em pData is 0 or \em size
                            is 0, the return value is a 0 pointer.
          */
+#ifdef EXV_USING_CPP_ELEVEN
+        static std::unique_ptr<TiffComponent> parse(
+            const byte*              pData,
+                  uint32_t           size,
+                  uint32_t           root,
+                  TiffHeaderBase*    pHeader
+        );
+#else
         static std::auto_ptr<TiffComponent> parse(
             const byte*              pData,
                   uint32_t           size,
                   uint32_t           root,
                   TiffHeaderBase*    pHeader
         );
+#endif
         /*!
           @brief Find primary groups in the source tree provided and populate
                  the list of primary groups.
diff --git a/src/tiffvisitor.cpp b/src/tiffvisitor.cpp
index 74f8d078..7a10c935 100644
--- a/src/tiffvisitor.cpp
+++ b/src/tiffvisitor.cpp
@@ -219,7 +219,11 @@ namespace Exiv2 {
             // Assumption is that the corresponding TIFF entry doesn't exist
             TiffPath tiffPath;
             TiffCreator::getPath(tiffPath, object->tag(), object->group(), root_);
+#ifdef EXV_USING_CPP_ELEVEN
+            pRoot_->addPath(object->tag(), tiffPath, pRoot_, std::move(clone));
+#else
             pRoot_->addPath(object->tag(), tiffPath, pRoot_, clone);
+#endif
 #ifdef DEBUG
             ExifKey key(object->tag(), groupName(object->group()));
             std::cerr << "Copied " << key << "\n";
@@ -1298,7 +1302,11 @@ namespace Exiv2 {
             // the TIFF structure table
             assert(tc.get());
             tc->setStart(p);
+#ifdef EXV_USING_CPP_ELEVEN
+            object->addChild(std::move(tc));
+#else
             object->addChild(tc);
+#endif
             p += 12;
         }
 
@@ -1310,7 +1318,11 @@ namespace Exiv2 {
 #endif
                 return;
             }
+#ifdef EXV_USING_CPP_ELEVEN
+            TiffComponent::AutoPtr tc(nullptr);
+#else
             TiffComponent::AutoPtr tc(0);
+#endif
             uint32_t next = getLong(p, byteOrder());
             if (next) {
                 tc = TiffCreator::create(Tag::next, object->group());
@@ -1330,7 +1342,11 @@ namespace Exiv2 {
                     return;
                 }
                 tc->setStart(pData_ + baseOffset() + next);
+#ifdef EXV_USING_CPP_ELEVEN
+                object->addNext(std::move(tc));
+#else
                 object->addNext(tc);
+#endif
             }
         } // object->hasNext()
 
@@ -1372,7 +1388,11 @@ namespace Exiv2 {
                 TiffComponent::AutoPtr td(new TiffDirectory(object->tag(),
                                                             static_cast<IfdId>(object->newGroup_ + i)));
                 td->setStart(pData_ + baseOffset() + offset);
+#ifdef EXV_USING_CPP_ELEVEN
+                object->addChild(std::move(td));
+#else
                 object->addChild(td);
+#endif
             }
         }
 #ifndef SUPPRESS_WARNINGS
@@ -1549,7 +1569,11 @@ namespace Exiv2 {
         	::free(buffer);
         }
 
+#ifdef EXV_USING_CPP_ELEVEN
+        object->setValue(std::move(v));
+#else
         object->setValue(v);
+#endif
         object->setData(pData, size);
         object->setOffset(offset);
         object->setIdx(nextIdx(object->group()));
@@ -1648,7 +1672,11 @@ namespace Exiv2 {
         assert(v.get());
         v->read(pData, size, bo);
 
+#ifdef EXV_USING_CPP_ELEVEN
+        object->setValue(std::move(v));
+#else
         object->setValue(v);
+#endif
         object->setOffset(0);
         object->setIdx(nextIdx(object->group()));
 
diff --git a/src/version.cpp b/src/version.cpp
index 8a21552d..e21a8e59 100644
--- a/src/version.cpp
+++ b/src/version.cpp
@@ -87,7 +87,7 @@ EXIV2_RCSID("@(#) $Id$")
 
 // Adobe XMP Toolkit
 #if EXV_HAVE_XMP_TOOLKIT
-#include "xmp.hpp"
+#include "xmp_exiv2.hpp"
 #endif
 
 // + standard includes
diff --git a/src/webpimage.cpp b/src/webpimage.cpp
index e4057d6c..20fe679d 100644
--- a/src/webpimage.cpp
+++ b/src/webpimage.cpp
@@ -65,8 +65,13 @@ namespace Exiv2 {
 namespace Exiv2 {
     using namespace Exiv2::Internal;
 
+#ifdef EXV_USING_CPP_ELEVEN
+    WebPImage::WebPImage(BasicIo::AutoPtr io)
+    : Image(ImageType::webp, mdNone, std::move(io))
+#else
     WebPImage::WebPImage(BasicIo::AutoPtr io)
     : Image(ImageType::webp, mdNone, io)
+#endif
     {
     } // WebPImage::WebPImage
 
@@ -687,7 +692,11 @@ namespace Exiv2 {
 
     Image::AutoPtr newWebPInstance(BasicIo::AutoPtr io, bool /*create*/)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new WebPImage(std::move(io)));
+#else
         Image::AutoPtr image(new WebPImage(io));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/src/xmp.cpp b/src/xmp_exiv2.cpp
similarity index 94%
rename from src/xmp.cpp
rename to src/xmp_exiv2.cpp
index 9d6aed8d..c8e2606a 100644
--- a/src/xmp.cpp
+++ b/src/xmp_exiv2.cpp
@@ -1,6 +1,6 @@
 // ***************************************************************** -*- C++ -*-
 /*
- * Copyright (C) 2004-2017 Andreas Huggel <ahuggel@gmx.net>
+ * Copyright (C) 2004-2015 Andreas Huggel <ahuggel@gmx.net>
  *
  * This program is part of the Exiv2 distribution.
  *
@@ -19,18 +19,18 @@
  * Foundation, Inc., 51 Franklin Street, 5th Floor, Boston, MA 02110-1301 USA.
  */
 /*
-  File:      xmp.cpp
-  Version:   $Rev$
+  File:      xmp_exiv2.cpp
+  Version:   $Rev: 4564 $
   Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
   History:   13-July-07, ahu: created
  */
 // *****************************************************************************
 #include "rcsid_int.hpp"
-EXIV2_RCSID("@(#) $Id$")
+EXIV2_RCSID("@(#) $Id: xmp_exiv2.cpp 4564 2016-09-25 22:43:40Z robinwmills $")
 
 // *****************************************************************************
 // included header files
-#include "xmp.hpp"
+#include "xmp_exiv2.hpp"
 #include "types.hpp"
 #include "error.hpp"
 #include "value.hpp"
@@ -45,7 +45,7 @@ EXIV2_RCSID("@(#) $Id$")
 // Adobe XMP Toolkit
 #ifdef EXV_HAVE_XMP_TOOLKIT
 # define TXMP_STRING_TYPE std::string
-# include <XMPSDK.hpp>
+# include <XMP.hpp>
 # include <XMP.incl_cpp>
 #endif // EXV_HAVE_XMP_TOOLKIT
 
@@ -261,7 +261,11 @@ namespace Exiv2 {
 
     Value::AutoPtr Xmpdatum::getValue() const
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        return p_->value_.get() == 0 ? Value::AutoPtr(nullptr) : p_->value_->clone();
+#else
         return p_->value_.get() == 0 ? Value::AutoPtr(0) : p_->value_->clone();
+#endif
     }
 
     const Value& Xmpdatum::value() const
@@ -401,28 +405,29 @@ namespace Exiv2 {
             xmpLockFct_ = xmpLockFct;
             pLockData_ = pLockData;
             initialized_ = SXMPMeta::Initialize();
-            SXMPMeta::RegisterNamespace("http://ns.adobe.com/lightroom/1.0/", "lr");
-            SXMPMeta::RegisterNamespace("http://rs.tdwg.org/dwc/index.htm", "dwc");
-            SXMPMeta::RegisterNamespace("http://purl.org/dc/terms/", "dcterms");
-            SXMPMeta::RegisterNamespace("http://www.digikam.org/ns/1.0/", "digiKam");
-            SXMPMeta::RegisterNamespace("http://www.digikam.org/ns/kipi/1.0/", "kipi");
-            SXMPMeta::RegisterNamespace("http://ns.microsoft.com/photo/1.0/", "MicrosoftPhoto");
-            SXMPMeta::RegisterNamespace("http://ns.acdsee.com/iptc/1.0/", "acdsee");
-            SXMPMeta::RegisterNamespace("http://iptc.org/std/Iptc4xmpExt/2008-02-29/", "iptcExt");
-            SXMPMeta::RegisterNamespace("http://ns.useplus.org/ldf/xmp/1.0/", "plus");
-            SXMPMeta::RegisterNamespace("http://ns.iview-multimedia.com/mediapro/1.0/", "mediapro");
-            SXMPMeta::RegisterNamespace("http://ns.microsoft.com/expressionmedia/1.0/", "expressionmedia");
-            SXMPMeta::RegisterNamespace("http://ns.microsoft.com/photo/1.2/", "MP");
-            SXMPMeta::RegisterNamespace("http://ns.microsoft.com/photo/1.2/t/RegionInfo#", "MPRI");
-            SXMPMeta::RegisterNamespace("http://ns.microsoft.com/photo/1.2/t/Region#", "MPReg");
-            SXMPMeta::RegisterNamespace("http://ns.google.com/photos/1.0/panorama/", "GPano");
-            SXMPMeta::RegisterNamespace("http://www.metadataworkinggroup.com/schemas/regions/", "mwg-rs");
-            SXMPMeta::RegisterNamespace("http://www.metadataworkinggroup.com/schemas/keywords/", "mwg-kw");
-            SXMPMeta::RegisterNamespace("http://ns.adobe.com/xmp/sType/Area#", "stArea");
-            SXMPMeta::RegisterNamespace("http://cipa.jp/exif/1.0/", "exifEX");
-		    SXMPMeta::RegisterNamespace("http://ns.adobe.com/camera-raw-saved-settings/1.0/", "crss");
-            SXMPMeta::RegisterNamespace("http://www.audio/", "audio");
-            SXMPMeta::RegisterNamespace("http://www.video/", "video");
+            std::string registeredNamespaces;
+            SXMPMeta::RegisterNamespace("http://ns.adobe.com/lightroom/1.0/", "lr", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://rs.tdwg.org/dwc/index.htm", "dwc", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://purl.org/dc/terms/", "dcterms", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://www.digikam.org/ns/1.0/", "digiKam", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://www.digikam.org/ns/kipi/1.0/", "kipi", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.microsoft.com/photo/1.0/", "MicrosoftPhoto", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.acdsee.com/iptc/1.0/", "acdsee", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://iptc.org/std/Iptc4xmpExt/2008-02-29/", "iptcExt", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.useplus.org/ldf/xmp/1.0/", "plus", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.iview-multimedia.com/mediapro/1.0/", "mediapro", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.microsoft.com/expressionmedia/1.0/", "expressionmedia", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.microsoft.com/photo/1.2/", "MP", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.microsoft.com/photo/1.2/t/RegionInfo#", "MPRI", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.microsoft.com/photo/1.2/t/Region#", "MPReg", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.google.com/photos/1.0/panorama/", "GPano", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://www.metadataworkinggroup.com/schemas/regions/", "mwg-rs", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://www.metadataworkinggroup.com/schemas/keywords/", "mwg-kw", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.adobe.com/xmp/sType/Area#", "stArea", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://cipa.jp/exif/1.0/", "exifEX", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://ns.adobe.com/camera-raw-saved-settings/1.0/", "crss", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://www.audio/", "audio", &registeredNamespaces);
+            SXMPMeta::RegisterNamespace("http://www.video/", "video", &registeredNamespaces);
         }
         return initialized_;
     }
@@ -504,11 +509,14 @@ namespace Exiv2 {
     void XmpParser::registerNs(const std::string& ns,
                                const std::string& prefix)
     {
+        std::string registeredNamespaces;
         try {
             initialize();
             AutoLock autoLock(xmpLockFct_, pLockData_);
+#ifdef DONT_HACK_NAMESPACE
             SXMPMeta::DeleteNamespace(ns.c_str());
-            SXMPMeta::RegisterNamespace(ns.c_str(), prefix.c_str());
+#endif
+            SXMPMeta::RegisterNamespace(ns.c_str(), prefix.c_str(), &registeredNamespaces);
         }
         catch (const XMP_Error& e) {
             throw Error(40, e.GetID(), e.GetErrMsg());
@@ -869,7 +877,9 @@ namespace {
         if (flags & Exiv2::XmpParser::useCompactFormat)    var |= kXMP_UseCompactFormat;
         if (flags & Exiv2::XmpParser::includeThumbnailPad) var |= kXMP_IncludeThumbnailPad;
         if (flags & Exiv2::XmpParser::exactPacketLength)   var |= kXMP_ExactPacketLength;
+#if 0 // DEPRECATED / NON EXISTENT IN CURRENT ADOBE XMP SDK (2017-01-05)
         if (flags & Exiv2::XmpParser::writeAliasComments)  var |= kXMP_WriteAliasComments;
+#endif
         if (flags & Exiv2::XmpParser::omitAllFormatting)   var |= kXMP_OmitAllFormatting;
         return var;
     }
diff --git a/src/xmpsidecar.cpp b/src/xmpsidecar.cpp
index eddbe8a2..24555901 100644
--- a/src/xmpsidecar.cpp
+++ b/src/xmpsidecar.cpp
@@ -36,7 +36,7 @@ EXIV2_RCSID("@(#) $Id$")
 #include "image.hpp"
 #include "basicio.hpp"
 #include "error.hpp"
-#include "xmp.hpp"
+#include "xmp_exiv2.hpp"
 #include "futils.hpp"
 #include "convert.hpp"
 
@@ -56,8 +56,13 @@ namespace {
 namespace Exiv2 {
 
 
+#ifdef EXV_USING_CPP_ELEVEN
+    XmpSidecar::XmpSidecar(BasicIo::AutoPtr io, bool create)
+        : Image(ImageType::xmp, mdXmp, std::move(io))
+#else
     XmpSidecar::XmpSidecar(BasicIo::AutoPtr io, bool create)
         : Image(ImageType::xmp, mdXmp, io)
+#endif
     {
         if (create) {
             if (io_->open() == 0) {
@@ -175,7 +180,11 @@ namespace Exiv2 {
     // free functions
     Image::AutoPtr newXmpInstance(BasicIo::AutoPtr io, bool create)
     {
+#ifdef EXV_USING_CPP_ELEVEN
+        Image::AutoPtr image(new XmpSidecar(std::move(io), create));
+#else
         Image::AutoPtr image(new XmpSidecar(io, create));
+#endif
         if (!image->good()) {
             image.reset();
         }
diff --git a/xmpsdk/CMakeLists.txt b/xmpsdk/CMakeLists.txt
deleted file mode 100644
index 77d98bc8..00000000
--- a/xmpsdk/CMakeLists.txt
+++ /dev/null
@@ -1,44 +0,0 @@
-# CMake build system for exiv2 library and executables
-# Copyright 2012-     Robin Mills      <robin@clanmills.com>
-# Copyright 2010-2012 Gilles Caulier   <caulier dot gilles at gmail dot com>
-# Copyright 2008      Patrick Spendrin <ps_ml at gmx dot de>
-
-# Redistribution and use is allowed according to the terms of the BSD license.
-# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
-
-include(../CMake_msvc.txt)
-msvc_runtime_configure(${EXIV2_ENABLE_SHARED} ${EXIV2_ENABLE_DYNAMIC_RUNTIME})
-
-if( POLICY CMP0026 )
-    cmake_policy(SET CMP0026 OLD) # Something to do with location
-endif()
-
-FOREACH(_currentfile ${XMPSRC})
-    # http://www.openguru.com/2009/04/cmake-detecting-platformoperating.html
-    IF(NOT MSVC AND NOT CYGWIN AND NOT MSYS AND NOT MINGW)
-        SET_SOURCE_FILES_PROPERTIES(${_currentfile} PROPERTIES COMPILE_FLAGS "-fPIC")
-    ENDIF()
-ENDFOREACH()
-
-if(NOT MSVC)
-  # http://stackoverflow.com/questions/10046114/in-cmake-how-can-i-test-if-the-compiler-is-clang
-  if ( NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang")
-    # 1123 - hide xmpsdk symbols
-    add_definitions( -fvisibility=hidden -fvisibility-inlines-hidden )
-  endif()
-endif()
-
-IF( EXIV2_ENABLE_XMP AND EXIV2_ENABLE_LIBXMP )
-    ADD_LIBRARY( xmp STATIC ${XMPSRC} )
-    GET_TARGET_PROPERTY( XMPLIB xmp LOCATION )
-    if ( NOT MSVC )
-        TARGET_LINK_LIBRARIES(xmp ${EXPAT_LIBRARIES})
-    else()
-        TARGET_LINK_LIBRARIES(xmp ${CMAKE_THREAD_LIBS_INIT} ${EXPAT_LIBRARIES})
-    endif()
-    # 1119  Install libxmp.a for use by third party applications (Thanks, Emmanuel)
-    INSTALL(TARGETS xmp ${INSTALL_TARGET_STANDARD_ARGS} )
-ENDIF()
-
-# That's all Folks!
-##
diff --git a/xmpsdk/Readme.txt b/xmpsdk/Readme.txt
new file mode 100644
index 00000000..ffd8db08
--- /dev/null
+++ b/xmpsdk/Readme.txt
@@ -0,0 +1,42 @@
+
+Adobe XMP SDK Instructions
+==========================
+
+Copy the include directory from the Adobe XMP SDK from the public directory into the exiv2 xmpsdk directory.
+
+MacOS
+=====
+
+Compile the SDK.
+
+Copy the generated files libXMPCoreStatic.a, and libXMPFilesStatic.a from the Adobe XMP SDK public folder.
+Make sure to rename libXMPCoreStatic.a to libXMPCore.a, and rename libXMPFilesStatic.a to libXMPFiles.a as
+well. Renaming the files can be using the ren-mac.sh bash script.
+
+
+Linux
+=====
+
+Compile the SDK.
+
+Copy the generated files staticXMPCore.a, and staticXMPFiles.a from the Adobe XMP SDK public folder.
+Make sure to rename libXMPCoreStatic.a to libXMPCore.a, and rename libXMPFilesStatic.a to libXMPFiles.a as
+well. Renaming the files can be using the ren-lnx.sh bash script.
+
+
+Windows
+=======
+
+Compile the SDK.
+
+Copy the generated files XMPCoreStatic.lib, and XMPFilesStatic.lib from the Adobe XMP SDK public folder.
+Make sure to rename XMPCoreStatic.lib to libXMPCore.lib, and rename XMPFilesStatic.lib to libXMPFiles.lib
+as well.
+
+
+Notes
+=====
+
+* On Mac the last version of the Adobe XMP SDK to compile and work with Exiv2 is version CC-2014.12.
+* Linux and Windows work with the latest version (as of now CC-2106.07.) of the Adobe XMP SDK.
+
diff --git a/xmpsdk/include/TXMPIterator.hpp b/xmpsdk/include/TXMPIterator.hpp
deleted file mode 100644
index 33c73a1f..00000000
--- a/xmpsdk/include/TXMPIterator.hpp
+++ /dev/null
@@ -1,235 +0,0 @@
-#ifndef __TXMPIterator_hpp__
-#define __TXMPIterator_hpp__ 1
-
-#if ( ! __XMP_hpp__ )
-    #error "Do not directly include, use XMPSDK.hpp"
-#endif
-
-// =================================================================================================
-// ADOBE SYSTEMS INCORPORATED
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved
-//
-// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-// =================================================================================================
-/// \file TXMPIterator.hpp
-/// \brief API for access to the XMP Toolkit iteration services.
-///
-/// \c TXMPIterator is the template class providing iteration services for the XMP Toolkit. It must
-/// be instantiated with a string class such as \c std::string. See the instructions in XMPSDK.hpp, and
-/// the Overview for a discussion of the overall architecture of the XMP API.
-// =================================================================================================
-
-// =================================================================================================
-/// \class TXMPIterator TXMPIterator.hpp
-/// @brief API for access to the XMP Toolkit iteration services.
-///
-/// \c TXMPIterator provides a uniform means to iterate over the schema and properties within an XMP
-/// object. \c TXMPIterator is a template class which must be instantiated with a string class such
-/// as \c std::string. See the instructions in XMPSDK.hpp, and the Overview for a discussion of the
-/// overall architecture of the XMP API. Access these functions through the concrete class,
-/// \c SXMPIterator.
-///
-/// @note Only XMP object iteration is currently available. Future development may include iteration
-/// over global tables, such as registered namespaces.
-///
-/// To understand how iteration works, you should have a thorough understanding of the XMP data
-/// tree, as described in the XMP Specification Part 1. You might also find it helpful to create
-/// some complex XMP and examine the output of \c TXMPMeta::DumpObject().
-///
-///   \li The top of the XMP data tree is a single root node. This does not explicitly appear in the
-///   dump and is never visited by an iterator; that is, it is never returned from
-///   \c TXMPIterator::Next().
-///
-///   \li Beneath the root are schema nodes; these collect the top-level properties in the same
-///   namespace. They are created and destroyed implicitly.
-///
-///   \li Beneath the schema nodes are the property nodes. The nodes below a property node depend on
-///   its type (simple, struct, or array) and whether it has qualifiers.
-///
-/// A \c TXMPIterator constructor defines a starting point for the iteration, and options that
-/// control how it proceeds. By default, iteration starts at the root and visits all nodes beneath
-/// it in a depth-first manner. The root node iteself is not visited; the first visited node is a
-/// schema node. You can provide a schema name or property path to select a different starting node.
-/// By default, this visits the named root node first then all nodes beneath it in a depth-first
-/// manner.
-///
-/// The function \c TXMPIterator::Next() delivers the schema URI, path, and option flags for the
-/// node being visited. If the node is simple, it also delivers the value. Qualifiers for this node
-/// are visited next. The fields of a struct or items of an array are visited after the qualifiers
-/// of the parent.
-///
-/// You can specify options when constructing the iteration object to control how the iteration is
-/// performed.
-///
-///   \li \c #kXMP_IterJustChildren - Visit just the immediate children of the root. Skip the root
-///   itself and all nodes below the immediate children. This omits the qualifiers of the immediate
-///   children, the qualifier nodes being below what they qualify.
-///   \li \c #kXMP_IterJustLeafNodes - Visit just the leaf property nodes and their qualifiers.
-///   \li \c #kXMP_IterJustLeafName - Return just the leaf component of the node names. The default
-///   is to return the full path name.
-///   \li \c #kXMP_IterIncludeAliases - Include aliases as part of the iteration. Since aliases are
-///   not actual nodes the default iteration does not visit them.
-///   \li \c #kXMP_IterOmitQualifiers - Do not visit the qualifiers of a node.
-// =================================================================================================
-
-#include "client-glue/WXMPIterator.hpp"
-
-template <class tStringObj> class TXMPIterator {
-
-public:
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Assignment operator, assigns the internal ref and increments the ref count.
-    ///
-    /// Assigns the internal reference from an existing object and increments the reference count on
-    /// the underlying internal XMP iterator.
-    ///
-    /// @param rhs An existing iteration object.
-
-    void operator= ( const TXMPIterator<tStringObj> & rhs );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Copy constructor, creates a client object refering to the same internal object.
-    ///
-    /// Creates a new client iterator that refers to the same underlying iterator as an existing object.
-    ///
-    /// @param original An existing iteration object to copy.
-
-    TXMPIterator ( const TXMPIterator<tStringObj> & original );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Constructs an iterator for properties within a schema in an XMP object.
-    ///
-    /// See the class description for the general operation of an  XMP object iterator.
-    /// Overloaded forms are provided to iterate the entire data tree,
-    /// a subtree rooted at a specific node, or properties within a specific schema.
-    ///
-    /// @param xmpObj The XMP object over which to iterate.
-    ///
-    /// @param schemaNS Optional schema namespace URI to restrict the iteration. To visit all of the
-    /// schema, pass 0 or the empty string "".
-    ///
-    /// @param propName Optional property name to restrict the iteration. May be an arbitrary path
-    /// expression. If provided, a schema URI must also be provided. To visit all properties, pass 0
-    /// or the empty string "".
-    ///
-    /// @param options Option flags to control the iteration. A logical OR of these bit flag constants:
-    ///   \li \c #kXMP_IterJustChildren - Visit only the immediate children of the root; default visits subtrees.
-    ///   \li \c #kXMP_IterJustLeafNodes - Visit only the leaf nodes; default visits all nodes.
-    ///   \li \c #kXMP_IterJustLeafName - Return just the leaf part of the path; default returns the full path.
-    ///   \li \c #kXMP_IterOmitQualifiers - Omit all qualifiers.
-    ///
-    /// @return The new TXMPIterator object.
-
-    TXMPIterator ( const TXMPMeta<tStringObj> & xmpObj,
-                   XMP_StringPtr  schemaNS,
-                   XMP_StringPtr  propName,
-                   XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Constructs an iterator for a subtree of properties within an XMP object.
-    ///
-    /// See the class description for the general operation of an  XMP object iterator. Overloaded
-    /// forms are provided to iterate the entire data tree, a subtree rooted at a specific node, or
-    /// properties within a specific schema.
-    ///
-    /// @param xmpObj The XMP object over which to iterate.
-    ///
-    /// @param schemaNS Optional schema namespace URI to restrict the iteration. To visit all of the
-    /// schema, pass 0 or the empty string "".
-    ///
-    /// @param options Option flags to control the iteration. A logical OR of these bit flag constants:
-    ///   \li \c #kXMP_IterJustChildren - Visit only the immediate children of the root; default visits subtrees.
-    ///   \li \c #kXMP_IterJustLeafNodes - Visit only the leaf nodes; default visits all nodes.
-    ///   \li \c #kXMP_IterJustLeafName - Return just the leaf part of the path; default returns the full path.
-    ///   \li \c #kXMP_IterOmitQualifiers - Omit all qualifiers.
-    ///
-    /// @return The new TXMPIterator object.
-
-    TXMPIterator ( const TXMPMeta<tStringObj> & xmpObj,
-                   XMP_StringPtr  schemaNS,
-                   XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Constructs an iterator for the entire data tree within an XMP object.
-    ///
-    /// See the class description for the general operation of an  XMP object iterator. Overloaded
-    /// forms are provided to iterate the entire data tree, a subtree rooted at a specific node, or
-    /// properties within a specific schema.
-    ///
-    /// @param xmpObj The XMP object over which to iterate.
-    ///
-    /// @param options Option flags to control the iteration. A logical OR of these bit flag constants:
-    ///   \li \c #kXMP_IterJustChildren - Visit only the immediate children of the root; default visits subtrees.
-    ///   \li \c #kXMP_IterJustLeafNodes - Visit only the leaf nodes; default visits all nodes.
-    ///   \li \c #kXMP_IterJustLeafName - Return just the leaf part of the path; default returns the full path.
-    ///   \li \c #kXMP_IterOmitQualifiers - Omit all qualifiers.
-    ///
-    /// @return The new \c TXMPIterator object.
-
-    TXMPIterator ( const TXMPMeta<tStringObj> & xmpObj,
-                   XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Constructs an iterator for the global tables of the XMP toolkit.	Not implemented.
-
-    TXMPIterator ( XMP_StringPtr  schemaNS,
-                   XMP_StringPtr  propName,
-                   XMP_OptionBits options );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Destructor, typical virtual destructor.
-
-    virtual ~TXMPIterator() throw();
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c Next() visits the next node in the iteration.
-    ///
-    /// Proceeds to the next node according to the options specified on creation of this object, and
-    /// delivers the schema URI, path, and option flags for the node being visited. If the node is
-    /// simple, it also delivers the value.
-    ///
-    /// @param schemaNS [out] A string object in which to return the assigned the schema namespace
-    /// URI of the current property. Can be null if the value is not wanted.
-    ///
-    /// @param propPath [out]  A string object in which to return the XPath name of the current
-    /// property. Can be null if the value is not wanted.
-    ///
-    /// @param propValue  [out] A string object in which to return the value of the current
-    /// property. Can be null if the value is not wanted.
-    ///
-    /// @param options  [out] A buffer in which to return the flags describing the current property,
-    /// which are a logical OR of \c #XMP_OptionBits bit-flag constants.
-    ///
-    /// @return True if there was another node to visit, false if the iteration is complete.
-
-    bool Next ( tStringObj *     schemaNS = 0,
-          		tStringObj *     propPath = 0,
-           		tStringObj *     propValue = 0,
-           		XMP_OptionBits * options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c Skip() skips some portion of the remaining iterations.
-    ///
-    /// @param options Option flags to control the iteration, a logical OR of these bit-flag
-    /// constants:
-    ///   \li \c #kXMP_IterSkipSubtree -  Skip the subtree below the current node.
-    ///   \li \c #kXMP_IterSkipSiblings - Skip the subtree below and remaining siblings of the current node.
-
-    void Skip ( XMP_OptionBits options );
-
-private:
-
-    XMPIteratorRef  iterRef;
-
-    TXMPIterator();	// ! Hidden, must choose property or table iteration.
-
-};  // class TXMPIterator
-
-// =================================================================================================
-
-#endif // __TXMPIterator_hpp__
diff --git a/xmpsdk/include/TXMPMeta.hpp b/xmpsdk/include/TXMPMeta.hpp
deleted file mode 100644
index 0bf04e15..00000000
--- a/xmpsdk/include/TXMPMeta.hpp
+++ /dev/null
@@ -1,1803 +0,0 @@
-#ifndef __TXMPMeta_hpp__
-#define __TXMPMeta_hpp__    1
-
-#if ( ! __XMP_hpp__ )
-    #error "Do not directly include, use XMPSDK.hpp"
-#endif
-
-// =================================================================================================
-// ADOBE SYSTEMS INCORPORATED
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-// =================================================================================================
-/// \file TXMPMeta.hpp
-/// \brief API for access to the XMP Toolkit core services.
-///
-/// \c TXMPMeta is the template class providing the core services of the XMP Toolkit. It must be
-/// instantiated with a string class such as \c std::string. Read the Toolkit Overview for
-/// information about the overall architecture of the XMP API, and the documentation for \c XMPSDK.hpp
-/// for specific instantiation instructions.
-///
-/// Access these functions through the concrete class, \c SXMPMeta.
-// =================================================================================================
-
-// =================================================================================================
-/// \class TXMPMeta TXMPMeta.hpp
-/// \brief API for access to the XMP Toolkit core services.
-///
-/// \c TXMPMeta is the template class providing the core services of the XMP Toolkit. It should be
-/// instantiated with a string class such as \c std::string. Read the Toolkit Overview for
-/// information about the overall architecture of the XMP API, and the documentation for \c XMPSDK.hpp
-/// for specific instantiation instructions.
-///
-/// Access these functions through the concrete class, \c SXMPMeta.
-///
-/// You can create \c TXMPMeta objects (also called XMP objects) from metadata that you construct,
-/// or that you obtain from files using the XMP Toolkit's XMPFiles component; see \c TXMPFiles.hpp.
-// =================================================================================================
-
-template <class tStringObj> class TXMPIterator;
-template <class tStringObj> class TXMPUtils;
-
-// -------------------------------------------------------------------------------------------------
-
-template <class tStringObj> class TXMPMeta {
-
-public:
-
-    // =============================================================================================
-    // Initialization and termination
-    // ==============================
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Initialization and termination
-    ///
-    /// @{
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetVersionInfo() retrieves runtime version information.
-    ///
-    /// The header \c XMPVersion.hpp defines a static version number for the XMP Toolkit, which
-    /// describes the version of the API used at client compile time. It is not necessarily the same
-    /// as the runtime version. Do not base runtime decisions on the static version alone; you can,
-    /// however, compare the runtime and static versions.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta). The
-    /// function can be called before calling \c TXMPMeta::Initialize().
-    ///
-    /// @param info [out] A buffer in which to return the version information.
-
-    static void GetVersionInfo ( XMP_VersionInfo * info );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c Initialize() explicitly initializes the XMP Toolkit before use. */
-
-    /// Initializes the XMP Toolkit.
-    ///
-    /// Call this function before making any other calls to the \c TXMPMeta functions, except
-    /// \c TXMPMeta::GetVersionInfo().
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @return True on success. */
-    static bool Initialize();
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c Terminate() explicitly terminates usage of the XMP Toolkit.
-    ///
-    /// Frees structures created on initialization.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-
-    static void Terminate();
-
-    /// @}
-
-    // =============================================================================================
-    // Constuctors and destructor
-    // =========================
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Constructors and destructor
-    /// @{
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Default constructor, creates an empty object.
-    ///
-    /// The default constructor creates a new empty \c TXMPMeta object.
-    ///
-    /// @return The new object. */
-    TXMPMeta();
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Copy constructor, creates a client object refering to the same internal object.
-    ///
-    /// The copy constructor creates a new \c TXMPMeta object that refers to the same internal XMP
-    /// object. as an existing \c TXMPMeta object.
-    ///
-    /// @param original The object to copy.
-    ///
-    /// @return The new object. */
-
-    TXMPMeta ( const TXMPMeta<tStringObj> & original );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Assignment operator, assigns the internal reference and increments the reference count.
-    ///
-    /// The assignment operator assigns the internal ref from the rhs object and increments the
-    /// reference count on the underlying internal XMP object.
-
-    void operator= ( const TXMPMeta<tStringObj> & rhs );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Reconstructs an XMP object from an internal reference.
-    ///
-    /// This constructor creates a new \c TXMPMeta object that refers to the underlying reference object
-    /// of an existing \c TXMPMeta object. Use to safely pass XMP objects across DLL boundaries.
-    ///
-    /// @param xmpRef The underlying reference object, obtained from some other XMP object with
-    /// \c TXMPMeta::GetInternalRef().
-    ///
-    /// @return The new object.
-
-    TXMPMeta ( XMPMetaRef xmpRef );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Constructs an object and parse one buffer of RDF into it.
-    ///
-    /// This constructor creates a new \c TXMPMeta object and populates it with metadata from a
-    /// buffer containing serialized RDF. This buffer must be a complete RDF parse stream.
-    ///
-    /// The result of passing serialized data to this function is identical to creating an empty
-    /// object then calling \c TXMPMeta::ParseFromBuffer(). To use the constructor, however, the RDF
-    /// must be complete. If you need to parse data from multiple buffers, create an empty object
-    /// and use  \c TXMPMeta::ParseFromBuffer().
-    ///
-    /// @param buffer  A pointer to the buffer of RDF to be parsed. Can be null if the length is 0;
-    /// in this case, the function creates an empty object.
-    ///
-    /// @param xmpSize  The length in bytes of the buffer.
-    ///
-    /// @return The new object.
-
-    TXMPMeta ( XMP_StringPtr buffer,
-               XMP_StringLen xmpSize );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Destructor, typical virtual destructor. */
-    virtual ~TXMPMeta() throw();
-
-    /// @}
-
-    // =============================================================================================
-    // Global state functions
-    // ======================
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Global option flags
-    /// @{
-    /// Global option flags affect the overall behavior of the XMP Toolkit. The available options
-    /// will be declared in \c XMP_Const.h. There are none in this version of the Toolkit.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetGlobalOptions() retrieves the set of global option flags. There are none in
-    /// this version of the Toolkit.
-    ///
-    /// This function is static; you can make the call from the class without instantiating it.
-    ///
-    /// @return A logical OR of global option bit-flag constants.
-
-     static XMP_OptionBits GetGlobalOptions();
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetGlobalOptions() updates the set of global option flags. There are none in this
-    /// version of the Toolkit.
-    ///
-    /// The entire set is replaced with the new values. If only one flag is to be modified, use
-    /// \c TXMPMeta::GetGlobalOptions() to obtain the current set, modify the desired flag, then use
-    /// this function to reset the value.
-    ///
-    /// This function is static; you can make the call from the class without instantiating it.
-    ///
-    /// @param options A logical OR of global option bit-flag constants.
-
-    static void SetGlobalOptions ( XMP_OptionBits options );
-
-    /// @}
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Internal data structure dump utilities
-    /// @{
-    ///
-    /// These are debugging utilities that dump internal data structures, to be handled by
-    /// client-defined callback described in \c XMP_Const.h.
-	///
-	/// @see Member function \c TXMPMeta::DumpObject()
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DumpNamespaces() sends the list of registered namespace URIs and prefixes to a handler.
-    ///
-    /// For debugging. Invokes a client-defined callback for each line of output.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @param outProc The client-defined procedure to handle each line of output.
-    ///
-    /// @param clientData A pointer to client-defined data to pass to the handler.
-    ///
-    /// @return	A success-fail status value, returned from the handler. Zero is success, failure
-    /// values are client-defined.
-
-    static XMP_Status DumpNamespaces ( XMP_TextOutputProc outProc,
-                     				   void *             clientData );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DumpAliases() sends the list of registered aliases and corresponding actuals to a handler.
-    ///
-    /// For debugging. Invokes a client-defined callback for each line of output.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @param outProc The client-defined procedure to handle each line of output.
-    ///
-    /// @param clientData A pointer to client-defined data to pass to the handler.
-    ///
-    /// @return	A success-fail status value, returned from the handler. Zero is success, failure
-    /// values are client-defined.
-
-    static XMP_Status DumpAliases ( XMP_TextOutputProc outProc,
-                  					void *             clientData );
-
-    /// @}
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Namespace Functions
-    /// @{
-    ///
-    /// Namespaces must be registered before use in namespace URI parameters or path expressions.
-    /// Within the XMP Toolkit the registered namespace URIs and prefixes must be unique. Additional
-    /// namespaces encountered when parsing RDF are automatically registered.
-    ///
-    /// The namespace URI should always end in an XML name separator such as '/' or '#'. This is
-    /// because some forms of RDF shorthand catenate a namespace URI with an element name to form a
-    /// new URI.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c RegisterNamespace() registers a namespace URI with a prefix.
-    ///
-    /// If the the prefix is in use, the URI of the existing prefix is overwritten.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @param namespaceURI The URI for the namespace. Must be a valid XML URI.
-    ///
-    /// @param prefix The prefix to be used. Must be a valid XML name.
-    ///
-    /// @note No checking is done on either the URI or the prefix.  */
-
-    static void RegisterNamespace ( XMP_StringPtr namespaceURI,
-                                    XMP_StringPtr prefix );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetNamespacePrefix() obtains the prefix for a registered namespace URI, and
-    /// reports whether the URI is registered.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @param namespaceURI The URI for the namespace. Must not be null or the empty string. It is
-    /// not an error if the namespace URI is not registered.
-    ///
-    /// @param namespacePrefix [out] A string object in which to return the prefix registered for
-    /// this URI, with a terminating colon character, ':'. If the namespace is not registered, this
-    /// string is not modified.
-    ///
-    /// @return True if the namespace URI is registered.
-
-    static bool GetNamespacePrefix ( XMP_StringPtr namespaceURI,
-                         			 tStringObj *  namespacePrefix );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetNamespaceURI() obtains the URI for a registered namespace prefix, and reports
-    /// whether the prefix is registered.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @param namespacePrefix The prefix for the namespace. Must not be null or the empty string.
-    /// It is not an error if the namespace prefix is not registered.
-    ///
-    /// @param namespaceURI [out] A string object in which to return the URI registered for this
-    /// prefix. If the prefix is not registered, this string is not modified.
-    ///
-    /// @return True if the namespace prefix is registered.
-
-    static bool GetNamespaceURI ( XMP_StringPtr namespacePrefix,
-                      			  tStringObj *  namespaceURI );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Not implemented.
-    ///
-    /// Deletes a namespace from the registry. Does nothing if the URI is not registered, or if the
-    /// parameter is null or the empty string.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @param namespaceURI The URI for the namespace.
-
-    static void DeleteNamespace ( XMP_StringPtr namespaceURI );
-
-    /// @}
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Alias functions
-    /// @{
-    ///
-    /// Aliases in XMP serve the same purpose as Windows file shortcuts, Mac OS file aliases, or
-    /// UNIX file symbolic links. The aliases are multiple names for the same property. One
-    /// distinction of XMP aliases is that they are ordered. An alias name points to an actual name;
-    /// the primary significance of the actual name is that it is the preferred name for output,
-    /// generally the most widely recognized name.
-    ///
-    /// XMP restricts the names that can be aliased. The alias must be a top-level property name,
-    /// not a field within a structure or an element within an array. The actual can be a top-level
-    /// property name, the first element within a top-level array, or the default element in an
-    /// alt-text array. This does not mean the alias can only be a simple property; you can alias a
-    /// top-level structure or array to an identical top-level structure or array, or to the first
-    /// item of an array of structures.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c RegisterAlias() associates an alias name with an actual name.
-    ///
-    /// Defines an alias mapping from one namespace/property to another. Both property names must be
-    /// simple names. An alias can be a direct mapping, where the alias and actual have the same
-    /// data type. It is also possible to map a simple alias to an item in an array. This can either
-    /// be to the first item in the array, or to the 'x-default' item in an alt-text array. Multiple
-    /// alias names can map to the same actual, as long as the forms match. It is a no-op to
-    /// reregister an alias in an identical fashion.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @param aliasNS The namespace URI for the alias. Must not be null or the empty string.
-    ///
-    /// @param aliasProp The name of the alias. Must be a simple name, not null or the empty string
-    /// and not a general path expression.
-    ///
-    /// @param actualNS The namespace URI for the actual. Must not be null or the empty string.
-    ///
-    /// @param actualProp The name of the actual. Must be a simple name, not null or the empty string
-    /// and not a general path expression.
-    ///
-    /// @param arrayForm Provides the array form for simple aliases to an array item. This is needed
-    /// to know what kind of array to create if set for the first time via the simple alias. Pass
-    /// \c #kXMP_NoOptions, the default value, for all direct aliases regardless of whether the actual
-    /// data type is an array or not. One of these constants:
-    ///
-    ///   \li \c #kXMP_NoOptions - This is a direct mapping. The actual data type does not matter.
-    ///   \li \c #kXMP_PropValueIsArray - The actual is an unordered array, the alias is to the
-    ///   first element of the array.
-    ///   \li \c #kXMP_PropArrayIsOrdered - The actual is an ordered array, the alias is to the
-    ///   first element of the array.
-    ///   \li \c #kXMP_PropArrayIsAlternate - The actual is an alternate array, the alias is to the
-    ///   first element of the array.
-    ///   \li \c #kXMP_PropArrayIsAltText - The actual is an alternate text array, the alias is to
-    ///   the 'x-default' element of the array.  */
-
-    static void RegisterAlias ( XMP_StringPtr  aliasNS,
-                    			XMP_StringPtr  aliasProp,
-                    			XMP_StringPtr  actualNS,
-                    			XMP_StringPtr  actualProp,
-                    			XMP_OptionBits arrayForm = kXMP_NoOptions );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ResolveAlias() reports whether a name is an alias, and what it is aliased to.
-    ///
-    /// Output strings are not written until return, so you can use this to
-    /// "reduce" a path to the base form as follows:
-    /// <pre>
-    ///   isAlias = SXMPMeta::ResolveAlias ( ns.c_str(), path.c_str(), &ns, &path, 0 );
-    /// </pre>
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @param aliasNS The namespace URI for the alias. Must not be null or the empty string.
-    ///
-    /// @param aliasProp The name of the alias. Can be an arbitrary path expression path, must not
-    /// null or the empty string.
-    ///
-    /// @param actualNS  [out] A string object in which to return the namespace URI for the actual.
-    /// Not modified if the given name is not an alias. Can be null if the namespace URI is not wanted.
-    ///
-    /// @param actualProp  [out] A string object in which to return the path of the actual.
-    /// Not modified if the given name is not an alias. Can be null if the actual's path is not wanted.
-    ///
-    /// @param arrayForm [out] A string object in which to return the array form of the actual. This
-    /// is 0 (\c #kXMP_NoOptions) if the alias and actual forms match, otherwise it is the options
-    /// passed to \c TXMPMeta::RegisterAlias(). Not modified if the given name is not an alias. Can
-    /// be null if the actual's array form is not wanted.
-    ///
-    /// @return True if the provided name is an alias.
-
-    static bool ResolveAlias ( XMP_StringPtr    aliasNS,
-                   			   XMP_StringPtr    aliasProp,
-                  			   tStringObj *     actualNS,
-                 			   tStringObj *     actualProp,
-                 			   XMP_OptionBits * arrayForm );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DeleteAlias() deletes an alias.
-    ///
-    /// This deletes only the registration of the alias, it does not delete the actual property.
-    /// It deletes any view of the property through the alias name.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @param aliasNS The namespace URI for the alias. Must not be null or the empty string.
-    ///
-    /// @param aliasProp The name of the alias. Must be a simple name, not null or the empty string
-    /// and not a general path expression. It is not an error to provide
-    /// a name that has not been registered as an alias.
-
-    static void DeleteAlias ( XMP_StringPtr aliasNS,
-                  			  XMP_StringPtr aliasProp );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c RegisterStandardAliases() registers all of the built-in aliases for a standard namespace.
-    ///
-    /// The built-in aliases are documented in the XMP Specification. This function registers the
-    /// aliases in the given namespace; that is, it creates the aliases from this namespace to
-    /// actuals in other namespaces.
-    ///
-    /// This function is static; make the call directly from the concrete class (\c SXMPMeta).
-    ///
-    /// @param schemaNS The namespace URI for the aliases. Must not be null or the empty string.
-
-    static void RegisterStandardAliases ( XMP_StringPtr schemaNS );
-
-    /// @}
-
-    // =============================================================================================
-    // Basic property manipulation functions
-    // =====================================
-
-    // *** Should add discussion of schemaNS and propName prefix usage.
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Accessing property values
-    /// @{
-    ///
-    /// The property value accessors all take a property specification; the top level namespace URI
-    ///	(the "schema" namespace) and the basic name of the property being referenced. See the
-    ///	introductory discussion of path expression usage for more information.
-	///
-    /// The accessor functions return true if the specified property exists. If it does, output
-    /// parameters return the value (if any) and option flags describing the property. The option
-    /// bit-flag constants that describe properties are \c kXMP_PropXx and
-	/// \c kXMP_ArrayIsXx. See \c #kXMP_PropValueIsURI and following, and macros \c #XMP_PropIsSimple
-	/// and following in \c XMP_Const.h. If the property exists and has a value, it is returned as a
-	/// Unicode string in UTF-8 encoding. Arrays and the non-leaf levels of structs do not have
-	/// values.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetProperty() reports whether a property exists, and retrieves its value.
-    ///
-    /// This is the simplest property accessor. Use this to retrieve the values of top-level simple
-    /// properties, or after using the path composition functions in \c TXMPUtils.
-    ///
-    /// When specifying a namespace and path (in this and all other accessors):
-    ///   \li If a namespace URI is specified, it must be for a registered namespace.
-    ///   \li If the namespace is specified only by a prefix in the property name path,
-    /// it must be a registered prefix.
-    ///   \li If both a URI and path prefix are present, they must be corresponding
-    /// parts of a registered namespace.
-    ///
-    /// @param schemaNS The namespace URI for the property. The URI must be for a registered
-    /// namespace. Can be null or the empty string if the first component of the \c propName path
-    /// contains a namespace prefix.
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string. The first component can be a namespace prefix; if present without a
-    /// \c schemaNS value, the prefix specifies the namespace. The prefix must be for a registered
-    /// namespace, and if a namespace URI is specified, must match the registered prefix for that
-    /// namespace.
-    ///
-    /// @param propValue [out] A string object in which to return the value of the property, if the
-    /// property exists and has a value. Arrays and non-leaf levels of structs do not have values.
-    /// Can be null if the value is not wanted.
-    ///
-    /// @param options A buffer in which to return option flags describing the property. Can be null
-    /// if the flags are not wanted.
-    ///
-    /// @return True if the property exists.
-
-    bool GetProperty ( XMP_StringPtr    schemaNS,
-                 	   XMP_StringPtr    propName,
-                       tStringObj *     propValue,
-                  	   XMP_OptionBits * options ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetArrayItem() provides access to items within an array.
-    ///
-    /// Reports whether the item exists; if it does, and if it has a value, the function retrieves
-    /// the value. Items are accessed by an integer index, where the first item has index 1.
-    ///
-    /// @param schemaNS The namespace URI for the array; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param itemIndex The 1-based index of the desired item. Use the macro \c #kXMP_ArrayLastItem
-    /// to specify the last existing array item.
-    ///
-    /// @param itemValue [out] A string object in which to return the value of the array item, if it
-    /// has a value. Arrays and non-leaf levels of structs do not have values. Can be null if the
-    /// value is not wanted.
-    ///
-    /// @param options [out] A buffer in which to return the option flags describing the array item.
-    /// Can be null if the flags are not wanted.
-    ///
-    /// @return True if the array item exists.
-
-    bool GetArrayItem ( XMP_StringPtr    schemaNS,
-                   		XMP_StringPtr    arrayName,
-                   		XMP_Index        itemIndex,
-                   		tStringObj *     itemValue,
-                   		XMP_OptionBits * options ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetStructField() provides access to fields within a nested structure.
-    ///
-    /// Reports whether the field exists; if it does, and if it has a value, the function retrieves
-    /// the value.
-    ///
-    /// @param schemaNS The namespace URI for the struct; see \c GetProperty().
-    ///
-    /// @param structName The name of the struct. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param fieldNS The namespace URI for the field. Same URI and prefix usage as the \c schemaNS
-    /// and \c structName parameters.
-    ///
-    /// @param fieldName The name of the field. Must be a single XML name, must not be null or the
-    /// empty string. Same URI and prefix usage as the \c schemaNS and \c structName parameters.
-    ///
-    /// @param fieldValue [out] A string object in which to return the value of the field, if the
-    /// field has a value. Arrays and non-leaf levels of structs do not have values. Can be null if
-    /// the value is not wanted.
-    ///
-    /// @param options [out] A buffer in which to return the option flags describing the field. Can
-    /// be null if the flags are not wanted.
-    ///
-    /// @return True if the field exists.
-
-    bool GetStructField ( XMP_StringPtr    schemaNS,
-                     	  XMP_StringPtr    structName,
-                     	  XMP_StringPtr    fieldNS,
-                     	  XMP_StringPtr    fieldName,
-                     	  tStringObj *     fieldValue,
-                     	  XMP_OptionBits * options ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetQualifier() provides access to a qualifier attached to a property.
-    ///
-    /// @note In this version of the Toolkit, qualifiers are supported only for simple leaf properties.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property to which the qualifier is attached. Can be a
-    /// general path expression, must not be null or the empty string; see \c GetProperty() for
-    /// namespace prefix usage.
-    ///
-    /// @param qualNS The namespace URI for the qualifier. Same URI and prefix usage as the
-    /// \c schemaNS and \c propName parameters.
-    ///
-    /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or
-    /// the empty string. Same URI and prefix usage as the \c schemaNS and \c propName parameters.
-    ///
-    /// @param qualValue [out] A string object in which to return the value of the qualifier, if the
-    /// qualifier has a value. Arrays and non-leaf levels of structs do not have values. Can be null
-    /// if the value is not wanted.
-    ///
-    /// @param options [out] A buffer in which to return the option flags describing the qualifier.
-    /// Can be null if the flags are not wanted.
-    ///
-    /// @return True if the qualifier exists.
-
-    bool GetQualifier ( XMP_StringPtr    schemaNS,
-                   		XMP_StringPtr    propName,
-                  		XMP_StringPtr    qualNS,
-                  		XMP_StringPtr    qualName,
-                   		tStringObj *     qualValue,
-                   		XMP_OptionBits * options ) const;
-
-    /// @}
-
-    // =============================================================================================
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Creating properties and setting their values
- 	/// @{
- 	///
-    /// These functions all take a property specification; the top level namespace URI (the "schema"
-    /// namespace) and the basic name of the property being referenced. See the introductory
-    /// discussion of path expression usage for more information.
-	///
-    /// All of the functions take a UTF-8 encoded Unicode string for the property value. Arrays and
-    /// non-leaf levels of structs do not have values. The value can be passed as an
-    /// \c #XMP_StringPtr (a pointer to a null-terminated string), or as a string object
-    /// (\c tStringObj).
-
-    /// Each function takes an options flag that describes the property. You can use these functions
-    /// to create empty arrays and structs by setting appropriate option flags. When you assign a
-    /// value, all levels of a struct that are implicit in the assignment are created if necessary.
-    /// \c TXMPMeta::AppendArrayItem() implicitly creates the named array if necessary.
-    ///
-    /// The allowed option bit-flags include:
-    ///   \li \c #kXMP_PropValueIsStruct - Can be used to create an empty struct.
-    ///		A struct is implicitly created when the first field is set.
-    ///   \li \c #kXMP_PropValueIsArray - By default, a general unordered array (bag).
-    ///   \li \c #kXMP_PropArrayIsOrdered - An ordered array.
-   	///   \li \c #kXMP_PropArrayIsAlternate - An alternative array.
-   	///   \li \c #kXMP_PropArrayIsAltText - An alt-text array. Each array element must
-    /// 	be a simple property with an \c xml:lang attribute.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetProperty() creates or sets a property value.
-    ///
-    /// This is the simplest property setter. Use it for top-level simple properties, or after using
-    /// the path composition functions in \c TXMPUtils.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue The new value, a pointer to a null terminated UTF-8 string. Must be null
-    /// for arrays and non-leaf levels of structs that do not have values.
-    ///
-    /// @param options Option flags describing the property; a logical OR of allowed bit-flag
-    /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property
-    /// that already exists.
-
-    void SetProperty ( XMP_StringPtr  schemaNS,
-					   XMP_StringPtr  propName,
-					   XMP_StringPtr  propValue,
-					   XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetProperty() creates or sets a property value using a string object.
-	///
-    /// Overloads the basic form of the function, allowing you to pass a string object
-	/// for the item value. It is otherwise identical; see details in the canonical form.
-
-    void SetProperty ( XMP_StringPtr      schemaNS,
-					   XMP_StringPtr      propName,
-					   const tStringObj & propValue,
-					   XMP_OptionBits     options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetArrayItem() creates or sets the value of an item within an array.
-    ///
-    /// Items are accessed by an integer index, where the first item has index 1. This function
-    /// creates the item if necessary, but the array itself must already exist Use
-    /// \c AppendArrayItem() to create arrays. A new item is automatically appended if the index is the
-    /// array size plus 1. To insert a new item before or after an existing item, use option flags.
-    ///
-    /// Use \c TXMPUtils::ComposeArrayItemPath() to create a complex path.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param itemIndex The 1-based index of the desired item. Use the macro \c #kXMP_ArrayLastItem
-    /// to specify the last existing array item.
-    ///
-    /// @param itemValue The new item value, a null-terminated UTF-8 string, if the array item has a
-    /// value.
-    ///
-    /// @param options Option flags describing the array type and insertion location for a new item;
-    /// a logical OR of allowed bit-flag constants. The type, if specified, must match the existing
-    /// array type, \c #kXMP_PropArrayIsOrdered, \c #kXMP_PropArrayIsAlternate, or
-    /// \c #kXMP_PropArrayIsAltText. Default (0 or \c #kXMP_NoOptions) matches the  existing array type.
-    ///
-    /// To insert a new item before or after the specified index, set flag \c #kXMP_InsertBeforeItem
-    /// or \c #kXMP_InsertAfterItem.
-
-    void SetArrayItem ( XMP_StringPtr  schemaNS,
-					    XMP_StringPtr  arrayName,
-					    XMP_Index      itemIndex,
-					    XMP_StringPtr  itemValue,
-					    XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetArrayItem() creates or sets the value of an item within an array using a string object.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object in which to
-	/// return the item value. It is otherwise identical; see details in the canonical form.
-
-    void SetArrayItem ( XMP_StringPtr      schemaNS,
-					    XMP_StringPtr      arrayName,
-					    XMP_Index          itemIndex,
-					    const tStringObj & itemValue,
-					    XMP_OptionBits     options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c AppendArrayItem() adds an item to an array, creating the array if necessary.
-    ///
-    /// This function simplifies construction of an array by not requiring that you pre-create an
-    /// empty array. The array that is assigned is created automatically if it does not yet exist.
-    /// If the array exists, it must have the form specified by the options. Each call appends a new
-    /// item to the array.
-    ///
-    /// Use \c TXMPUtils::ComposeArrayItemPath() to create a complex path.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param arrayOptions Option flags describing the array type to create; a logical OR of
-    /// allowed bit-flag constants, \c #kXMP_PropArrayIsOrdered, \c #kXMP_PropArrayIsAlternate, or
-    /// \c #kXMP_PropArrayIsAltText. If the array exists, must match the existing array type or be
-    /// null (0 or \c #kXMP_NoOptions).
-    ///
-    /// @param itemValue The new item value, a null-terminated UTF-8 string, if the array item has a
-    /// value.
-    ///
-    /// @param itemOptions Option flags describing the item type to create; one of the bit-flag
-    /// constants \c #kXMP_PropValueIsArray or \c #kXMP_PropValueIsStruct to create a complex array
-    /// item.
-
-    void AppendArrayItem ( XMP_StringPtr  schemaNS,
-						   XMP_StringPtr  arrayName,
-						   XMP_OptionBits arrayOptions,
-						   XMP_StringPtr  itemValue,
-						   XMP_OptionBits itemOptions = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c AppendArrayItem() adds an item to an array using a string object value, creating
-    /// the array if necessary.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object in which to
-	/// return the item value. It is otherwise identical; see details in the canonical form.
-
-    void AppendArrayItem ( XMP_StringPtr      schemaNS,
-						   XMP_StringPtr      arrayName,
-						   XMP_OptionBits     arrayOptions,
-						   const tStringObj & itemValue,
-						   XMP_OptionBits     itemOptions = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetStructField() creates or sets the value of a field within a nested structure.
-    ///
-    /// Use this to  set a value within an existing structure, create a new field within an existing
-    /// structure, or create an empty structure of any depth. If you set a field in a structure that
-    /// does not exist, the structure is automatically created.
-    ///
-    /// Use \c TXMPUtils::ComposeStructFieldPath() to create a complex path.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param structName The name of the struct. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param fieldNS The namespace URI for the field. Same namespace and prefix usage as
-    /// \c GetProperty().
-    ///
-    /// @param fieldName The name of the field. Must be a single XML name, must not be null or the
-    /// empty string. Same namespace and prefix usage as \c GetProperty().
-    ///
-    /// @param fieldValue The new value, a null-terminated UTF-8 string, if the field has a value.
-    /// Null to create a new, empty struct or empty field in an existing struct.
-    ///
-    /// @param options Option flags describing the property, in which the bit-flag
-    /// \c #kXMP_PropValueIsStruct must be set to create a struct.
-
-    void SetStructField ( XMP_StringPtr   schemaNS,
-						  XMP_StringPtr   structName,
-						  XMP_StringPtr   fieldNS,
-						  XMP_StringPtr   fieldName,
-						  XMP_StringPtr   fieldValue,
-						  XMP_OptionBits  options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetStructField() creates or sets the value of a field within a nested structure,
-    /// using a string object.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object in which to
-	/// return the field value. It is otherwise identical; see details in the canonical form.
-
-    void SetStructField ( XMP_StringPtr      schemaNS,
-						  XMP_StringPtr      structName,
-						  XMP_StringPtr      fieldNS,
-						  XMP_StringPtr      fieldName,
-						  const tStringObj & fieldValue,
-						  XMP_OptionBits     options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetQualifier() creates or sets a qualifier attached to a property.
-    ///
-    /// Use this to  set a value for an existing qualifier, or create a new qualifier. <<how do
-    /// options work? macro vs bit-flag? interaction w/XMP_PropHasQualifier?>> Use
-    /// \c TXMPUtils::ComposeQualifierPath() to create a complex path.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property to which the qualifier is attached. Can be a
-    /// general path expression, must not be null or the empty string; see \c GetProperty() for
-    /// namespace prefix usage.
-    ///
-    /// @param qualNS The namespace URI for the qualifier. Same namespace and prefix usage as
-    /// \c GetProperty().
-    ///
-    /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or
-    /// the empty string. Same namespace and prefix usage as \c GetProperty().
-    ///
-    /// @param qualValue The new value, a null-terminated UTF-8 string, if the qualifier has a
-    /// value. Null to create a new, empty qualifier.
-    ///
-    /// @param options Option flags describing the <<qualified property? qualifier?>>, a logical OR
-    /// of property-type bit-flag constants. Use the macro \c #XMP_PropIsQualifier to create a
-    /// qualifier.	 <<??>>
-
-    void SetQualifier ( XMP_StringPtr  schemaNS,
-					    XMP_StringPtr  propName,
-					    XMP_StringPtr  qualNS,
-					    XMP_StringPtr  qualName,
-					    XMP_StringPtr  qualValue,
-					    XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetQualifier() creates or sets a qualifier attached to a property using a string object.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object
-	/// for the qualifier value. It is otherwise identical; see details in the canonical form.
-
-    void SetQualifier ( XMP_StringPtr      schemaNS,
-					    XMP_StringPtr      propName,
-					    XMP_StringPtr      qualNS,
-					    XMP_StringPtr      qualName,
-					    const tStringObj & qualValue,
-					    XMP_OptionBits     options = 0 );
-
-    /// @}
-
-    // =============================================================================================
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Detecting and deleting properties.
-    /// @{
-    ///
-    /// The namespace URI and prefix usage for property specifiers in these functions is the same as
-    /// for \c TXMPMeta::GetProperty().
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DeleteProperty() deletes an XMP subtree rooted at a given property.
-    ///
-    /// It is not an error if the property does not exist.
-    ///
-    /// @param schemaNS The namespace URI for the property; see \c GetProperty().
-    ///
-    /// @param propName The name of the property; see \c GetProperty().
-
-    void DeleteProperty ( XMP_StringPtr schemaNS,
-                     	  XMP_StringPtr propName );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DeleteArrayItem() deletes an XMP subtree rooted at a given array item.
-    ///
-    /// It is not an error if the array item does not exist. Use
-    /// \c TXMPUtils::ComposeArrayItemPath() to create a complex path.
-    ///
-    /// @param schemaNS The namespace URI for the array; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param itemIndex The 1-based index of the desired item. Use the macro \c #kXMP_ArrayLastItem
-    /// to specify the last existing array item.
-
-    void DeleteArrayItem ( XMP_StringPtr schemaNS,
-						   XMP_StringPtr arrayName,
-						   XMP_Index     itemIndex );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DeleteStructField() deletes an XMP subtree rooted at a given struct field.
-    ///
-    /// It is not an error if the field does not exist.
-    ///
-    /// @param schemaNS The namespace URI for the struct; see \c GetProperty().
-    ///
-    /// @param structName The name of the struct. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param fieldNS The namespace URI for the field. Same namespace and prefix usage as
-    /// \c GetProperty().
-    ///
-    /// @param fieldName The name of the field. Must be a single XML name, must not be null or the
-    /// empty string. Same namespace and prefix usage as \c GetProperty().
-
-    void DeleteStructField ( XMP_StringPtr schemaNS,
-							 XMP_StringPtr structName,
-							 XMP_StringPtr fieldNS,
-							 XMP_StringPtr fieldName );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DeleteQualifier() deletes an XMP subtree rooted at a given qualifier.
-    ///
-    /// It is not an error if the qualifier does not exist.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property to which the qualifier is attached. Can be a
-    /// general path expression, must not be null or the empty string; see \c GetProperty() for
-    /// namespace prefix usage.
-    ///
-    /// @param qualNS The namespace URI for the qualifier. Same namespace and prefix usage as
-    /// \c GetProperty().
-    ///
-    /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or
-    /// the empty string. Same namespace and prefix usage as \c GetProperty().
-
-    void DeleteQualifier ( XMP_StringPtr schemaNS,
-						   XMP_StringPtr propName,
-						   XMP_StringPtr qualNS,
-						   XMP_StringPtr qualName );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DoesPropertyExist() reports whether a property currently exists.
-    ///
-    /// @param schemaNS The namespace URI for the property; see \c GetProperty().
-    ///
-    /// @param propName The name of the property; see \c GetProperty().
-    ///
-    /// @return True if the property exists.
-
-    bool DoesPropertyExist ( XMP_StringPtr schemaNS,
-                        	 XMP_StringPtr propName ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DoesArrayItemExist() reports whether an array item currently exists.
-    ///
-    /// Use \c TXMPUtils::ComposeArrayItemPath() to create a complex path.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param itemIndex The 1-based index of the desired item. Use the macro \c #kXMP_ArrayLastItem
-    /// to specify the last existing array item.
-    ///
-    /// @return True if the array item exists.
-
-    bool DoesArrayItemExist ( XMP_StringPtr schemaNS,
-							  XMP_StringPtr arrayName,
-							  XMP_Index     itemIndex ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DoesStructFieldExist() reports whether a struct field currently exists.
-    ///
-    /// Use \c TXMPUtils::ComposeStructFieldPath() to create a complex path.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param structName The name of the struct. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param fieldNS The namespace URI for the field. Same namespace and prefix usage as
-    /// \c GetProperty().
-    ///
-    /// @param fieldName The name of the field. Must be a single XML name, must not be null or the
-    /// empty string. Same namespace and prefix usage as \c GetProperty().
-    ///
-    /// @return True if the field exists.
-
-    bool DoesStructFieldExist ( XMP_StringPtr schemaNS,
-							    XMP_StringPtr structName,
-							    XMP_StringPtr fieldNS,
-							    XMP_StringPtr fieldName ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DoesQualifierExist() reports whether a qualifier currently exists.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property to which the qualifier is attached. Can be a
-    /// general path expression, must not be null or the empty string; see \c GetProperty() for
-    /// namespace prefix usage.
-    ///
-    /// @param qualNS The namespace URI for the qualifier. Same namespace and prefix usage as
-    /// \c GetProperty().
-    ///
-    /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or
-    /// the empty string. Same namespace and prefix usage as \c GetProperty().
-    ///
-    /// @return True if the qualifier exists.
-
-    bool DoesQualifierExist ( XMP_StringPtr schemaNS,
-							  XMP_StringPtr propName,
-							  XMP_StringPtr qualNS,
-							  XMP_StringPtr qualName ) const;
-
-    /// @}
-
-    // =============================================================================================
-    // Specialized Get and Set functions
-    // =============================================================================================
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Accessing properties as binary values.
-    /// @{
-    ///
-	/// These are very similar to \c TXMPMeta::GetProperty() and \c TXMPMeta::SetProperty(), except
-	/// that the value is returned or provided in binary form instead of as a UTF-8 string.
-	/// \c TXMPUtils provides functions for converting between binary and string values.
-    /// Use the path composition functions in  \c TXMPUtils	to compose complex path expressions
-    /// for fields or items in nested structures or arrays, or for qualifiers.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetProperty_Bool() retrieves the value of a Boolean property as a C++ bool.
-    ///
-    /// Reports whether a property exists, and retrieves its binary value and property type information.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue [out] A buffer in which to return the binary value. Can be null if the
-    /// value is not wanted. Must be null for arrays and non-leaf levels of structs that do not have
-    /// values.
-    ///
-    /// @param options [out] A buffer in which to return the option flags describing the property, a
-    /// logical OR of allowed bit-flag constants; see \c #kXMP_PropValueIsStruct and following. Can
-    /// be null if flags are not wanted.
-    ///
-    /// @return True if the property exists.
-
-    bool GetProperty_Bool ( XMP_StringPtr    schemaNS,
-						    XMP_StringPtr    propName,
-						    bool *           propValue,
-						    XMP_OptionBits * options ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetProperty_Int() retrieves the value of an integer property as a C long integer.
-    ///
-    /// Reports whether a property exists, and retrieves its binary value and property type information.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue [out] A buffer in which to return the binary value. Can be null if the
-    /// value is not wanted. Must be null for arrays and non-leaf levels of structs that do not have
-    /// values.
-    ///
-    /// @param options [out] A buffer in which to return the option flags describing the property, a
-    /// logical OR of allowed bit-flag constants; see \c #kXMP_PropValueIsStruct and following. Can
-    /// be null if flags are not wanted.
-    ///
-    /// @return True if the property exists.
-
-    bool GetProperty_Int ( XMP_StringPtr    schemaNS,
-						   XMP_StringPtr    propName,
-						   long *           propValue,
-						   XMP_OptionBits * options ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetProperty_Int64() retrieves the value of an integer property as a C long long integer.
-    ///
-    /// Reports whether a property exists, and retrieves its binary value and property type information.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue [out] A buffer in which to return the binary value. Can be null if the
-    /// value is not wanted. Must be null for arrays and non-leaf levels of structs that do not have
-    /// values.
-    ///
-    /// @param options [out] A buffer in which to return the option flags describing the property, a
-    /// logical OR of allowed bit-flag constants; see \c #kXMP_PropValueIsStruct and following. Can
-    /// be null if flags are not wanted.
-    ///
-    /// @return True if the property exists.
-
-    bool GetProperty_Int64 ( XMP_StringPtr    schemaNS,
-							 XMP_StringPtr    propName,
-							 long long *      propValue,
-							 XMP_OptionBits * options ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetProperty_Float() retrieves the value of a floating-point property as a C double float.
-    ///
-    /// Reports whether a property exists, and retrieves its binary value and property type information.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue [out] A buffer in which to return the binary value. Can be null if the
-    /// value is not wanted. Must be null for arrays and non-leaf levels of structs that do not have
-    /// values.
-    ///
-    /// @param options [out] A buffer in which to return the option flags describing the property, a
-    /// logical OR of allowed bit-flag constants; see \c #kXMP_PropValueIsStruct and following. Can
-    /// be null if flags are not wanted.
-    ///
-    /// @return True if the property exists.
-
-    bool GetProperty_Float ( XMP_StringPtr    schemaNS,
-							 XMP_StringPtr    propName,
-							 double *         propValue,
-							 XMP_OptionBits * options ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetProperty_Date() retrieves the value of a date-time property as an \c #XMP_DateTime structure.
-    ///
-    /// Reports whether a property exists, and retrieves its binary value and property type information.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue [out] A buffer in which to return the binary value. Can be null if the
-    /// value is not wanted. Must be null for arrays and non-leaf levels of structs that do not have
-    /// values.
-    ///
-    /// @param options [out] A buffer in which to return the option flags describing the property, a
-    /// logical OR of allowed bit-flag constants; see \c #kXMP_PropValueIsStruct and following. Can
-    /// be null if flags are not wanted.
-    ///
-    /// @return True if the property exists.
-
-    bool GetProperty_Date ( XMP_StringPtr    schemaNS,
-						    XMP_StringPtr    propName,
-						    XMP_DateTime *   propValue,
-						    XMP_OptionBits * options ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetProperty_Bool() sets the value of a Boolean property using a C++ bool.
-    ///
-    /// Sets a property with a binary value, creating it if necessary.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue The new binary value. Can be null if creating the property. Must be null
-    /// for arrays and non-leaf levels of structs that do not have values.
-    ///
-    /// @param options Option flags describing the property; a logical OR of allowed bit-flag
-    /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property
-    /// that already exists.
-
-    void SetProperty_Bool ( XMP_StringPtr  schemaNS,
-						    XMP_StringPtr  propName,
-						    bool           propValue,
-						    XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetProperty_Int() sets the value of an integer property using a C long integer.
-    ///
-    /// Sets a property with a binary value, creating it if necessary.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue The new binary value. Can be null if creating the property. Must be null
-    /// for arrays and non-leaf levels of structs that do not have values.
-    ///
-    /// @param options Option flags describing the property; a logical OR of allowed bit-flag
-    /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property
-    /// that already exists.
-
-    void SetProperty_Int ( XMP_StringPtr  schemaNS,
-						   XMP_StringPtr  propName,
-						   long           propValue,
-						   XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetProperty_Int64() sets the value of an integer property using a C long long integer.
-    ///
-    /// Sets a property with a binary value, creating it if necessary.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue The new binary value. Can be null if creating the property. Must be null
-    /// for arrays and non-leaf levels of structs that do not have values.
-    ///
-    /// @param options Option flags describing the property; a logical OR of allowed bit-flag
-    /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property
-    /// that already exists.
-
-    void SetProperty_Int64 ( XMP_StringPtr  schemaNS,
-							 XMP_StringPtr  propName,
-							 long long      propValue,
-							 XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetProperty_Float() sets the value of a floating-point property using a C double float.
-    ///
-    /// Sets a property with a binary value, creating it if necessary.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue The new binary value. Can be null if creating the property. Must be null
-    /// for arrays and non-leaf levels of structs that do not have values.
-    ///
-    /// @param options Option flags describing the property; a logical OR of allowed bit-flag
-    /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property
-    /// that already exists.
-
-    void SetProperty_Float ( XMP_StringPtr  schemaNS,
-							 XMP_StringPtr  propName,
-							 double         propValue,
-							 XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetProperty_Date() sets the value of a date/time property using an \c #XMP_DateTime structure.
-    ///
-    /// Sets a property with a binary value, creating it if necessary.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param propValue The new binary value. Can be null if creating the property. Must be null
-    /// for arrays and non-leaf levels of structs that do not have values.
-    ///
-    /// @param options Option flags describing the property; a logical OR of allowed bit-flag
-    /// constants; see \c #kXMP_PropValueIsStruct and following. Must match the type of a property
-    /// that already exists.
-
-    void SetProperty_Date ( XMP_StringPtr         schemaNS,
-						    XMP_StringPtr         propName,
-						    const XMP_DateTime &  propValue,
-						    XMP_OptionBits        options = 0 );
-
-    /// @}
-    // =============================================================================================
-    /// \name Accessing localized text (alt-text) properties.
-    /// @{
-    ///
-	/// Localized text properties are stored in alt-text arrays. They allow multiple concurrent
-	/// localizations of a property value, for example a document title or copyright in several
-	/// languages.
-    ///
-    /// These functions provide convenient support for localized text properties, including a
-    /// number of special and obscure aspects. The most important aspect of these functions is that
-    /// they select an appropriate array item based on one or two RFC 3066 language tags. One of
-    /// these languages, the "specific" language, is preferred and selected if there is an exact
-    /// match. For many languages it is also possible to define a "generic" language that can be
-    /// used if there is no specific language match. The generic language must be a valid RFC 3066
-    /// primary subtag, or the empty string.
-    ///
-    /// For example, a specific language of "en-US" should be used in the US, and a specific
-    /// language of "en-UK" should be used in England. It is also appropriate to use "en" as the
-    /// generic language in each case. If a US document goes to England, the "en-US" title is
-    /// selected by using the "en" generic language and the "en-UK" specific language.
-    ///
-    /// It is considered poor practice, but allowed, to pass a specific language that is just an
-    /// RFC 3066 primary tag. For example "en" is not a good specific language, it should only be
-    /// used as a generic language. Passing "i" or "x" as the generic language is also considered
-    /// poor practice but allowed.
-    ///
-    /// Advice from the W3C about the use of RFC 3066 language tags can be found at:
-    ///     \li http://www.w3.org/International/articles/language-tags/
-    ///
-    /// \note RFC 3066 language tags must be treated in a case insensitive manner. The XMP toolkit
-    /// does this by normalizing their capitalization:
- 	/// 	\li The primary subtag is lower case, the suggested practice of ISO 639.
-	/// 	\li All 2 letter secondary subtags are upper case, the suggested practice of ISO 3166.
-	/// 	\li All other subtags are lower case.
-    ///
-    /// The XMP specification defines an artificial language, "x-default", that is used to
-    /// explicitly denote a default item in an alt-text array. The XMP toolkit normalizes alt-text
-    /// arrays such that the x-default item is the first item. The \c SetLocalizedText() function
-    /// has several special features related to the x-default item, see its description for details.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetLocalizedText() retrieves information about a selected item in an alt-text array.
-    ///
-    /// The array item is selected according to these rules:
-    ///   \li Look for an exact match with the specific language.
-    ///   \li If a generic language is given, look for a partial match.
-    ///   \li Look for an x-default item.
-    ///   \li Choose the first item.
-    ///
-    /// A partial match with the generic language is where the start of the item's language matches
-    /// the generic string and the next character is '-'. An exact match is also recognized as a
-    /// degenerate case.
-    ///
-    /// You can pass "x-default" as the specific language. In this case, selection of an
-    /// \c x-default item is an exact match by the first rule, not a selection by the 3rd rule. The
-    /// last 2 rules are fallbacks used when the specific and generic languages fail to produce a
-    /// match.
-    ///
-    /// The return value reports whether a match was successfully made.
-    ///
-    /// @param schemaNS The namespace URI for the alt-text array; see \c GetProperty().
-    ///
-    /// @param altTextName The name of the alt-text array. Can be a general path expression, must
-    /// not be null or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param genericLang The name of the generic language as an RFC 3066 primary subtag. Can be
-    /// null or the empty string if no generic language is wanted.
-    ///
-    /// @param specificLang The name of the specific language as an RFC 3066 tag, or "x-default".
-    /// Must not be null or the empty string.
-    ///
-    /// @param actualLang [out] A string object in which to return the language of the selected
-    /// array item, if an appropriate array item is found. Can be null if the language is not wanted.
-    ///
-    /// @param itemValue [out] A string object in which to return the value of the array item, if an
-    /// appropriate array item is found. Can be null if the value is not wanted.
-    ///
-    /// @param options A buffer in which to return the option flags that describe the array item, if
-    /// an appropriate array item is found. Can be null if the flags are not wanted.
-    ///
-    /// @return True if an appropriate array item exists.
-
-    bool GetLocalizedText ( XMP_StringPtr    schemaNS,
-						    XMP_StringPtr    altTextName,
-						    XMP_StringPtr    genericLang,
-						    XMP_StringPtr    specificLang,
-						    tStringObj *     actualLang,
-						    tStringObj *     itemValue,
-						    XMP_OptionBits * options ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetLocalizedText() modifies the value of a selected item in an alt-text array.
-    ///
-    /// Creates an appropriate array item if necessary, and handles special cases for the x-default
-    /// item.
-    ///
-    /// The array item is selected according to these rules:
-    ///   \li Look for an exact match with the specific language.
-    ///   \li If a generic language is given, look for a partial match.
-    ///   \li Look for an x-default item.
-    ///   \li Choose the first item.
-    ///
-    /// A partial match with the generic language is where the start of the item's language matches
-    /// the generic string and the next character is '-'. An exact match is also recognized as a
-    /// degenerate case.
-    ///
-    /// You can pass "x-default" as the specific language. In this case, selection of an
-    /// \c x-default item is an exact match by the first rule, not a selection by the 3rd rule. The
-    /// last 2 rules are fallbacks used when the specific and generic languages fail to produce a
-    /// match.
-    ///
-    /// Item values are modified according to these rules:
-    ///
-    ///   \li If the selected item is from a match with the specific language, the value of that
-    ///   item is modified. If the existing value of that item matches the existing value of the
-    ///   x-default item, the x-default item is also modified. If the array only has 1 existing item
-    ///   (which is not x-default), an x-default item is added with the given value.
-    ///
-    ///   \li If the selected item is from a match with the generic language and there are no other
-    ///   generic matches, the value of that item is modified. If the existing value of that item
-    ///   matches the existing value of the x-default item, the x-default item is also modified. If
-    ///   the array only has 1 existing item (which is not x-default), an x-default item is added
-    ///   with the given value.
-    ///
-    ///   \li If the selected item is from a partial match with the generic language and there are
-    ///   other partial matches, a new item is created for the specific language. The x-default item
-    ///   is not modified.
-    ///
-    ///   \li If the selected item is from the last 2 rules then a new item is created for the
-    ///   specific language. If the array only had an x-default item, the x-default item is also
-    ///   modified. If the array was empty, items are created for the specific language and
-    ///   x-default.
-    ///
-    /// @param schemaNS The namespace URI for the alt-text array; see \c GetProperty().
-    ///
-    /// @param altTextName The name of the alt-text array. Can be a general path expression, must
-    /// not be null or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param genericLang The name of the generic language as an RFC 3066 primary subtag. Can be
-    /// null or the empty string if no generic language is wanted.
-    ///
-    /// @param specificLang The name of the specific language as an RFC 3066 tag, or "x-default".
-    /// Must not be null or the empty string.
-    ///
-    /// @param itemValue The new value for the matching array item, specified as a null-terminated
-    /// UTF-8 string.
-    ///
-    /// @param options Option flags, none currently defined.
-
-    void SetLocalizedText ( XMP_StringPtr  schemaNS,
-						    XMP_StringPtr  altTextName,
-						    XMP_StringPtr  genericLang,
-						    XMP_StringPtr  specificLang,
-						    XMP_StringPtr  itemValue,
-						    XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetLocalizedText() modifies the value of a selected item in an alt-text array using
-    /// a string object.
-    ///
-    /// Creates an appropriate array item if necessary, and handles special cases for the x-default
-    /// item.
-    ///
-    /// The array item is selected according to these rules:
-    ///   \li Look for an exact match with the specific language.
-    ///   \li If a generic language is given, look for a partial match.
-    ///   \li Look for an x-default item.
-    ///   \li Choose the first item.
-    ///
-    /// A partial match with the generic language is where the start of the item's language matches
-    /// the generic string and the next character is '-'. An exact match is also recognized as a
-    /// degenerate case.
-    ///
-    /// You can pass "x-default" as the specific language. In this case, selection of an \c x-default
-    /// item is an exact match by the first rule, not a selection by the 3rd rule. The last 2 rules
-    /// are fallbacks used when the specific and generic languages fail to produce a match.
-    ///
-    /// Item values are modified according to these rules:
-    ///
-    ///   \li If the selected item is from a match with the specific language, the value of that
-    ///   item is modified. If the existing value of that item matches the existing value of the
-    ///   x-default item, the x-default item is also modified. If the array only has 1 existing item
-    ///   (which is not x-default), an x-default item is added with the given value.
-    ///
-    ///   \li If the selected item is from a match with the generic language and there are no other
-    ///   generic matches, the value of that item is modified. If the existing value of that item
-    ///   matches the existing value of the x-default item, the x-default item is also modified. If
-    ///   the array only has 1 existing item (which is not x-default), an x-default item is added
-    ///   with the given value.
-    ///
-    ///   \li If the selected item is from a partial match with the generic language and there are
-    ///   other partial matches, a new item is created for the specific language. The x-default item
-    ///   is not modified.
-    ///
-    ///   \li If the selected item is from the last 2 rules then a new item is created for the
-    ///   specific language. If the array only had an x-default item, the x-default item is also
-    ///   modified. If the array was empty, items are created for the specific language and
-    ///   x-default.
-    ///
-    /// @param schemaNS The namespace URI for the alt-text array; see \c GetProperty().
-    ///
-    /// @param altTextName The name of the alt-text array. Can be a general path expression, must
-    /// not be null or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param genericLang The name of the generic language as an RFC 3066 primary subtag. Can be
-    /// null or the empty string if no generic language is wanted.
-    ///
-    /// @param specificLang The name of the specific language as an RFC 3066 tag, or "x-default".
-    /// Must not be null or the empty string.
-    ///
-    /// @param itemValue The new value for the matching array item, specified as a string object.
-    ///
-    /// @param options Option flags, none currently defined.
-
-    void SetLocalizedText ( XMP_StringPtr      schemaNS,
-						    XMP_StringPtr      altTextName,
-						    XMP_StringPtr      genericLang,
-						    XMP_StringPtr      specificLang,
-						    const tStringObj & itemValue,
-						    XMP_OptionBits     options = 0 );
-
-    /// @}
-
-   	// =============================================================================================
-    /// \name Creating and reading serialized RDF.
-    /// @{
-    ///
-	/// The metadata contained in an XMP object must be serialized as RDF for storage in an XMP
-	/// packet and output to a file. Similarly, metadata in the form of serialized RDF (such as
-	/// metadata read from a file using \c TXMPFiles) must be parsed into an XMP object for
-	/// manipulation with the XMP Toolkit.
-	///
-	/// These functions support parsing serialized RDF into an XMP object, and serializing an XMP
-    /// object into RDF. The input for parsing can be any valid Unicode encoding. ISO Latin-1 is
-    /// also recognized, but its use is strongly discouraged. Serialization is always as UTF-8.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ParseFromBuffer() parses RDF from a series of input buffers into this XMP object.
-    ///
-    /// Use this to convert metadata from serialized RDF form (as, for example, read from an XMP
-    /// packet embedded in a file) into an XMP object that you can manipulate with the XMP Toolkit.
-    /// If this XMP object is empty and the input buffer contains a complete XMP packet, this is the
-    /// same as creating a new XMP object from that buffer with the constructor.
-    ///
-    /// You can use this function to combine multiple buffers into a single metadata tree. To
-    /// terminate an input loop conveniently, pass  the option \c #kXMP_ParseMoreBuffers for all
-    /// real input, then make a final call with a zero length and \c #kXMP_NoOptions. The buffers
-    /// can be any length. The buffer boundaries need not respect XML tokens or even Unicode
-    /// characters.
-    ///
-    /// @param buffer A pointer to a buffer of input. Can be null if \c bufferSize is 0.
-    ///
-    /// @param bufferSize The length of the input buffer in bytes. Zero is a valid value.
-    ///
-    /// @param options An options flag that controls how the parse operation is performed. A logical
-    /// OR of these bit-flag constants:
-    ///   \li \c #kXMP_ParseMoreBuffers - This is not the last buffer of input, more calls follow.
-    ///   \li \c #kXMP_RequireXMPMeta - The \c x:xmpmeta XML element is required around \c rdf:RDF.
-    ///
-    /// @see \c TXMPFiles::GetXMP()
-
-    void ParseFromBuffer ( XMP_StringPtr  buffer,
-						   XMP_StringLen  bufferSize,
-						   XMP_OptionBits options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SerializeToBuffer() serializes metadata in this XMP object into a string as RDF.
-    ///
-    /// Use this to prepare metadata for storage as an XMP packet embedded in a file. See \c TXMPFiles::PutXMP().
-    ///
-    /// @param rdfString [out] A string object in which to return the serialized RDF. Must not be null.
-    ///
-    /// @param options An options flag that controls how the serialization operation is performed.
-    /// The specified options must be logically consistent; an exception is thrown if they are not.
-    /// A logical OR of these bit-flag constants:
-    ///   \li \c kXMP_OmitPacketWrapper - Do not include an XML packet wrapper. This cannot be
-    ///   specified together with \c #kXMP_ReadOnlyPacket, \c #kXMP_IncludeThumbnailPad, or
-    ///   \c #kXMP_ExactPacketLength.
-    ///   \li \c kXMP_ReadOnlyPacket - Create a read-only XML packet wapper. Cannot be specified
-    ///   together with \c kXMP_OmitPacketWrapper.
-    ///   \li \c kXMP_UseCompactFormat - Use a highly compact RDF syntax and layout.
-    ///   \li \c kXMP_WriteAliasComments - Include XML comments for aliases.
-    ///   \li \c kXMP_IncludeThumbnailPad - Include typical space for a JPEG thumbnail in the
-    ///   padding if no \c xmp:Thumbnails property is present. Cannot be specified together with
-    ///   \c kXMP_OmitPacketWrapper.
-    ///   \li \c kXMP_ExactPacketLength - The padding parameter provides the overall packet length.
-    ///   The actual amount of padding is computed. An exception is thrown if the packet exceeds
-    ///   this length with no padding.	Cannot be specified together with
-    ///   \c kXMP_OmitPacketWrapper.
-    ///
-    /// In addition to the above options, you can include one of the following encoding options:
-    ///   \li \c #kXMP_EncodeUTF8 - Encode as UTF-8, the default.
-    ///   \li \c #kXMP_EncodeUTF16Big - Encode as big-endian UTF-16.
-    ///   \li \c #kXMP_EncodeUTF16Little - Encode as little-endian UTF-16.
-    ///   \li \c #kXMP_EncodeUTF32Big - Encode as big-endian UTF-32.
-    ///   \li \c #kXMP_EncodeUTF32Little - Encode as little-endian UTF-32.
-    ///
-    /// @param padding The amount of padding to be added if a writeable XML packet is created. If
-    /// zero (the default) an appropriate amount of padding is computed.
-    ///
-    /// @param newline The string to be used as a line terminator. If empty, defaults to linefeed,
-    /// U+000A, the standard XML newline.
-    ///
-    /// @param indent The string to be used for each level of indentation in the serialized RDF. If
-    /// empty, defaults to two ASCII spaces, U+0020.
-    ///
-    /// @param baseIndent The number of levels of indentation to be used for the outermost XML
-    /// element in the serialized RDF. This is convenient when embedding the RDF in other text.
-
-    void SerializeToBuffer ( tStringObj *   rdfString,
-							 XMP_OptionBits options,
-							 XMP_StringLen  padding,
-							 XMP_StringPtr  newline,
-							 XMP_StringPtr  indent = "",
-							 XMP_Index      baseIndent = 0 ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SerializeToBuffer() serializes metadata in this XMP object into a string as RDF.
-    ///
-    /// This simpler form of the function uses default values for the \c newline, \c indent, and
-    /// \c baseIndent parameters.
-    ///
-    /// @param rdfString [out] A string object in which to return the serialized RDF. Must not be null.
-    ///
-    /// @param options An options flag that controls how the serialization operation is performed.
-    /// The specified options must be logically consistent; an exception is thrown if they are not.
-    /// A logical OR of these bit-flag constants:
-    ///   \li \c kXMP_OmitPacketWrapper - Do not include an XML packet wrapper. This cannot be
-    ///   specified together with \c #kXMP_ReadOnlyPacket, \c #kXMP_IncludeThumbnailPad, or
-    ///   \c #kXMP_ExactPacketLength.
-    ///   \li \c kXMP_ReadOnlyPacket - Create a read-only XML packet wapper. Cannot be specified
-    ///   together with \c kXMP_OmitPacketWrapper.
-    ///   \li \c kXMP_UseCompactFormat - Use a highly compact RDF syntax and layout.
-    ///   \li \c kXMP_WriteAliasComments - Include XML comments for aliases.
-    ///   \li \c kXMP_IncludeThumbnailPad - Include typical space for a JPEG thumbnail in the
-    ///   padding if no \c xmp:Thumbnails property is present. Cannot be specified together with
-    ///   \c kXMP_OmitPacketWrapper.
-    ///   \li \c kXMP_ExactPacketLength - The padding parameter provides the overall packet length.
-    ///   The actual amount of padding is computed. An exception is thrown if the packet exceeds
-    ///   this length with no padding.	Cannot be specified together with
-    ///   \c kXMP_OmitPacketWrapper.
-    ///
-    /// In addition to the above options, you can include one of the following encoding options:
-    ///   \li \c #kXMP_EncodeUTF8 - Encode as UTF-8, the default.
-    ///   \li \c #kXMP_EncodeUTF16Big - Encode as big-endian UTF-16.
-    ///   \li \c #kXMP_EncodeUTF16Little - Encode as little-endian UTF-16.
-    ///   \li \c #kXMP_EncodeUTF32Big - Encode as big-endian UTF-32.
-    ///   \li \c #kXMP_EncodeUTF32Little - Encode as little-endian UTF-32.
-    ///
-    /// @param padding The amount of padding to be added if a writeable XML packet is created.
-    /// If zero (the default) an appropriate amount of padding is computed.
-
-    void SerializeToBuffer ( tStringObj *   rdfString,
-							 XMP_OptionBits options = 0,
-							 XMP_StringLen  padding = 0 ) const;
-
-    /// @}
-    // =============================================================================================
-    // Miscellaneous Member Functions
-    // ==============================
-
-    // ---------------------------------------------------------------------------------------------
-    /// \name Helper functions.
-    /// @{
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Retrieves an internal reference that can be safely passed across DLL boundaries and
-    /// reconstructed.
-    ///
-    /// The \c TXMPMeta class is a normal C++ template, it is instantiated and local to each client
-    /// executable, as are the other \c TXMP* classes. Different clients might not use the same
-    /// string type to instantiate \c TXMPMeta.
-    ///
-    /// Because of this you should not pass \c SXMPMeta objects, or pointers to \c SXMPMeta objects,
-    /// across DLL boundaries. Use this function to obtain a safe internal reference that you can
-    /// pass, then construct a local object on the callee side. This construction does not create a
-    /// cloned XMP tree, it is the same underlying XMP object safely wrapped in each client's
-    /// \c SXMPMeta object.
-    ///
-    /// Use this function and the associated constructor like this:
-    ///   \li The callee's header contains:
-    /// <pre>
-    /// CalleeMethod ( XMPMetaRef xmpRef );
-    /// </pre>
-    ///
-    ///   \li The caller's code contains:
-    /// <pre>
-    /// SXMPMeta callerXMP;
-    /// CalleeMethod ( callerXMP.GetInternalRef() );
-    /// </pre>
-    ///
-    ///   \li The callee's code contains:
-    /// <pre>
-    /// SXMPMeta calleeXMP ( xmpRef );
-    /// </pre>
-    ///
-    /// @return The reference object.
-
-    XMPMetaRef GetInternalRef() const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c GetObjectName() retrieves the client-assigned name of this XMP object.
-    ///
-    /// Assign this name with \c SetObjectName().
-    ///
-    /// @param name [out] A string object in which to return the name.
-
-    void GetObjectName ( tStringObj * name ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetObjectName() assigns a name to this XMP object.
-    ///
-    /// Retrieve this client-assigned name with \c GetObjectName().
-    ///
-    /// @param name The name as a null-terminated UTF-8 string.
-
-    void SetObjectName ( XMP_StringPtr name );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetObjectName() assigns a name to this XMP object.
-    ///
-    /// Retrieve this client-assigned name with \c GetObjectName().
-    ///
-    /// @param name The name as a string object.
-
-    void SetObjectName ( tStringObj name );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c Sort() sorts the data model tree of an XMP object.
-    ///
-    /// Use this function to sort the data model of an XMP object into a canonical order. This can
-    /// be convenient when comparing data models, (e.g. by text comparison of DumpObject output).
-    ///
-    /// At the top level the namespaces are sorted by their prefixes. Within a namespace, the top
-    /// level properties are sorted by name. Within a struct, the fields are sorted by their
-    /// qualified name, i.e. their XML prefix:local form. Unordered arrays of simple items are
-    /// sorted by value. Language Alternative arrays are sorted by the xml:lang qualifiers, with
-    /// the "x-default" item placed first.
-    
-    void Sort();
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c Erase() restores the object to a "just constructed" state.
-    
-    void Erase();
-    
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c Clone() creates a deep copy of an XMP object.
-    ///
-    /// Use this function to copy an entire XMP metadata tree. Assignment and copy constructors only
-    /// increment a reference count, they do not do a deep copy. This function returns an object,
-    /// not a pointer. The following shows correct usage:
-    ///
-    /// <pre>
-    /// SXMPMeta * clone1 = new SXMPMeta ( sourceXMP.Clone() );  // This works.
-    /// SXMPMeta   clone2 ( sourceXMP.Clone );  	// This works also. (Not a pointer.)
-    /// </pre>
-    /// The \c clone2 example does not use an explicit pointer.
-    /// This is good for local usage, protecting against memory leaks.
-    ///
-    /// This is an example of incorrect usage:
-    /// <pre>
-    /// SXMPMeta * clone3 = &sourceXMP.Clone();		// ! This does not work!
-    /// </pre>
-    /// The assignment to \c clone3 creates a temporary object, initializes it with the clone,
-    /// assigns the address of the temporary to \c clone3, then deletes the temporary.
-    ///
-    /// @param options Option flags, not currently defined..
-    ///
-    /// @return An XMP object cloned from the original.
-
-    TXMPMeta Clone ( XMP_OptionBits options = 0 ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c CountArrayItems() reports the number of items currently defined in an array.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @return The number of items.
-
-    XMP_Index CountArrayItems ( XMP_StringPtr schemaNS,
-                      			XMP_StringPtr arrayName ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DumpObject() outputs the content of an XMP object to a callback handler for debugging.
-    ///
-    /// Invokes a client-defined callback for each line of output.
-    ///
-    /// @param outProc The client-defined procedure to handle each line of output.
-    ///
-    /// @param clientData A pointer to client-defined data to pass to the handler.
-    ///
-    /// @return	A success-fail status value, returned from the handler. Zero is success, failure
-    /// values are client-defined.
-    ///
-    /// @see Static functions \c DumpNamespaces() and \c DumpAliases()
-
-    XMP_Status DumpObject ( XMP_TextOutputProc outProc,
-                 			void *	           clientData ) const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief Not implemented
-    XMP_OptionBits GetObjectOptions() const;
-
-    // ---------------------------------------------------------------------------------------------
-    /// \brief Not implemented
-    void SetObjectOptions ( XMP_OptionBits options );
-
-    /// @}
-
-    // =============================================================================================
-
-    XMPMetaRef xmpRef;  // *** Should be private, see below.
-
-private:
-
-#if 0	// *** VS.Net and gcc seem to not handle the friend declarations properly.
-    friend class TXMPIterator <class tStringObj>;
-    friend class TXMPUtils <class tStringObj>;
-#endif
-
-};  // class TXMPMeta
-
-#endif  // __TXMPMeta_hpp__
diff --git a/xmpsdk/include/TXMPUtils.hpp b/xmpsdk/include/TXMPUtils.hpp
deleted file mode 100644
index d7189770..00000000
--- a/xmpsdk/include/TXMPUtils.hpp
+++ /dev/null
@@ -1,965 +0,0 @@
-#ifndef __TXMPUtils_hpp__
-#define __TXMPUtils_hpp__ 1
-
-#if ( ! __XMP_hpp__ )
-    #error "Do not directly include, use XMPSDK.hpp"
-#endif
-
-// =================================================================================================
-// ADOBE SYSTEMS INCORPORATED
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved
-//
-// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-// =================================================================================================
-/// \file TXMPUtils.hpp
-/// \brief API for access to the XMP Toolkit utility services.
-///
-/// \c TXMPUtils is the template class providing utility services for the XMP Toolkit. It must be
-/// instantiated with a string class such as \c std::string. See the instructions in XMPSDK.hpp, and
-/// the Overview for a discussion of the overall architecture of the XMP API.
-// =================================================================================================
-
-// =================================================================================================
-/// \class TXMPUtils TXMPUtils.hpp
-/// @brief API for access to the XMP Toolkit utility services.
-///
-/// \c TXMPUtils is a template class which must be instantiated with a string class such as
-/// \c std::string. See the instructions in XMPSDK.hpp, and the Overview for a discussion of the overall
-/// architecture of the XMP API.
-///
-/// This class defines helper functions that support the basic metadata manipulation provided by
-/// \c TXMPMeta. All of the functions are static; that is, you call them directly from the concrete
-/// class (\c SXMPUtils), which is never itself instantiated.
-///
-/// General categories of utilities include:
-///
-///   \li Composing complex path expressions, which you can then pass to the property access
-///   functions in \c TXMPMeta
-///   \li Converting between binary and string forms of property values
-///   \li Manipulating date/time values
-///   \li Encoding and decoding base-64 strings
-///   \li JPEG file handling
-///   \li Editing aids for creating a user interface for the XMP Toolkit
-// =================================================================================================
-
-template <class tStringObj> class TXMPUtils {
-
-public:
-
-    // =============================================================================================
-    // No constructors or destructor declared or needed
-    // ================================================
-
-    //  ============================================================================================
-    /// \name Path composition
-    /// @{
-    ///
-    /// These functions provide support for composing path expressions to deeply nested properties.
-    /// The functions in \c TXMPMeta such as \c TXMPMeta::GetProperty(),
-    /// \c TXMPMeta::GetArrayItem(), and \c TXMPMeta::GetStructField() provide easy access to top level
-    /// simple properties, items in top level arrays, and fields of top level structs.	They are
-    /// not as convenient for more complex things, such as fields several levels deep in a complex
-    /// struct, or fields within an array of structs, or items of an array that is a field of a
-    /// struct. You can use these utility functions to compose these paths, which you can then pass
-    /// to the property access functions. You can also compose	paths to top-level array items or
-	/// struct fields so that you can use the binary accessors such as
-	/// \c TXMPMeta::GetProperty_Int().
-    ///
-    /// You can use these functions is to compose a complete path expression, or all but the last
-    /// component. For example, suppose you have a property that is an array of integers within a
-    /// struct. You can access one of the array items like this:
-    ///
-    /// <pre>
-    ///   SXMPUtils::ComposeStructFieldPath ( schemaNS, "Struct", fieldNS, "Array", &path );
-    ///   SXMPUtils::ComposeArrayItemPath ( schemaNS, path, index, &path );
-    ///   exists = xmpObj.GetProperty_Int ( schemaNS, path, &value, &options );
-    /// </pre>
-    ///
-    /// You could also use this code if you want the string form of the integer:
-    ///
-    /// <pre>
-    ///   SXMPUtils::ComposeStructFieldPath ( schemaNS, "Struct", fieldNS, "Array", &path );
-    ///   xmpObj.GetArrayItem ( schemaNS, path, index, &value, &options );
-    /// </pre>
-    ///
-    /// \note It might look confusing that the \c schemaNS is passed in all of the calls above. This
-    /// is because the XMP Toolkit keeps the top-level "schema" namespace separate from the rest of
-    /// the path expression.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ComposeArrayItemPath() composes the path expression for an item in an array.
-    ///
-    /// The returned string is in the form <tt>ns:arrayName[i]</tt>, where "ns" is the prefix for
-    /// the specified namespace, and "i" is the decimal representation of specified item index.
-    /// If the last item was specified, the path is <tt>ns:arrayName[last()]</tt>.
-    ///
-    /// @param schemaNS The namespace URI for the array; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param itemIndex The 1-based index of the desired item. Use the macro
-    /// \c #kXMP_ArrayLastItem to specify the last existing array item.
-    ///
-    /// @param fullPath [out] A string in which to return the composed path.
-
-    static void ComposeArrayItemPath ( XMP_StringPtr schemaNS,
-									   XMP_StringPtr arrayName,
-									   XMP_Index     itemIndex,
-									   tStringObj *  fullPath );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ComposeStructFieldPath() composes the path expression for a field in a struct.
-    ///
-    /// The returned string is in the form <tt>ns:structName/fNS:fieldName</tt>, where "ns" is the
-    /// prefix for the schema namespace, and "fNS" is the prefix for field namespace.
-    ///
-    /// @param schemaNS The namespace URI for the struct; see \c GetProperty().
-    ///
-    /// @param structName The name of the struct. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param fieldNS The namespace URI for the field. Same URI and prefix usage as the
-    /// \c schemaNS and \c structName parameters.
-    ///
-    /// @param fieldName The name of the field. Must be a single XML name, must not be null or the
-    /// empty string. Same URI and prefix usage as the \c schemaNS and \c structName parameters.
-    ///
-    /// @param fullPath [out] A string in which to return the composed path.
-
-    static void ComposeStructFieldPath ( XMP_StringPtr schemaNS,
-										 XMP_StringPtr structName,
-										 XMP_StringPtr fieldNS,
-										 XMP_StringPtr fieldName,
-										 tStringObj *  fullPath );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ComposeQualifierPath() composes the path expression for a qualifier.
-    ///
-    /// The returned string is in the form <tt>ns:propName/?qNS:qualName</tt>, where "ns" is the
-    /// prefix for the schema namespace, and "qNS" is the prefix for the qualifier namespace.
-    ///
-    /// @param schemaNS The namespace URI; see \c GetProperty().
-    ///
-    /// @param propName The name of the property to which the qualifier is attached. Can be a
-    /// general path expression, must not be null or the empty string; see \c GetProperty() for
-    /// namespace prefix usage.
-    ///
-    /// @param qualNS The namespace URI for the qualifier. Same URI and prefix usage as the
-    /// \c schemaNS and \c propName parameters.
-    ///
-    /// @param qualName The name of the qualifier. Must be a single XML name, must not be null or the
-    /// empty string. Same URI and prefix usage as the \c schemaNS and \c propName parameters.
-    ///
-    /// @param fullPath [out] A string in which to return the composed path.
-
-    static void ComposeQualifierPath ( XMP_StringPtr schemaNS,
-									   XMP_StringPtr propName,
-									   XMP_StringPtr qualNS,
-									   XMP_StringPtr qualName,
-									   tStringObj *  fullPath );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ComposeLangSelector() composes the path expression to select an alternate item by language.
-    ///
-    /// Path syntax allows two forms of "content addressing" to select an item in an array of
-    /// alternatives. The form used in this function lets you select an item in an alt-text array
-    /// based on the value of its \c xml:lang qualifier. The other form of content addressing is
-    /// shown in \c ComposeFieldSelector().
-    ///
-    /// The returned string is in the form <tt>ns:arrayName[\@xml:lang='langName']</tt>, where
-    /// "ns" is the prefix for the schema namespace
-    ///
-    /// This function provides a path expression that is explicitly and only for a specific
-    /// language. In most cases, \c TXMPMeta::SetLocalizedText() and \c TXMPMeta::GetLocalizedText()
-    /// are preferred, because they provide extra logic to choose the appropriate language and
-    /// maintain consistency with the 'x-default' value.
-    ///
-    /// @param schemaNS The namespace URI for the array; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param langName The RFC 3066 code for the desired language, as a null-terminated UTF-8 string.
-    ///
-    /// @param fullPath [out] A string in which to return the composed path.
-
-    static void ComposeLangSelector ( XMP_StringPtr schemaNS,
-									  XMP_StringPtr arrayName,
-									  XMP_StringPtr langName,
-									  tStringObj *  fullPath );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ComposeLangSelector() composes a path expression to select an alternate item by language.
-    ///
-    /// Path syntax allows two forms of "content addressing" to select an item in an array of
-    /// alternatives. The form used in this function lets you select an item in an alt-text array
-    /// based on the value of its \c xml:lang qualifier. The other form of content addressing is
-    /// shown in \c ComposeFieldSelector().
-    ///
-    /// The returned string is in the form <tt>ns:arrayName[\@xml:lang='langName']</tt>, where
-    /// "ns" is the prefix for the schema namespace
-    ///
-    /// This function provides a path expression that is explicitly and only for a specific
-    /// language. In most cases, \c TXMPMeta::SetLocalizedText() and \c TXMPMeta::GetLocalizedText()
-    /// are preferred, because they provide extra logic to choose the appropriate language and
-    /// maintain consistency with the 'x-default' value.
-    ///
-    /// @param schemaNS The namespace URI for the array; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param langName The RFC 3066 code for the desired language, as a string object.
-    ///
-    /// @param fullPath [out] A string in which to return the composed path.
-
-    static void ComposeLangSelector ( XMP_StringPtr      schemaNS,
-									  XMP_StringPtr      arrayName,
-									  const tStringObj & langName,
-									  tStringObj *       fullPath );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ComposeFieldSelector() composes a path expression to select an alternate item by a field's value.
-    ///
-    /// Path syntax allows two forms of "content addressing" to select an item in an array of
-    /// alternatives. The form used in this function lets you select an item in an array of structs
-    /// based on the value of one of the fields in the structs. The other form of content addressing
-    /// is shown in \c ComposeLangSelector().
-    ///
-    /// For example, consider a simple struct that has two fields, the name of a city and the URI of
-    /// an FTP site in that city. Use this to create an array of download alternatives. You can show
-    /// the user a popup built from the values of the city fields, then get the corresponding URI as
-    /// follows:
-    /// <pre>
-    ///   ComposeFieldSelector ( schemaNS, "Downloads", fieldNS, "City", chosenCity, &path );
-    ///   exists = GetStructField ( schemaNS, path, fieldNS, "URI", &uri );
-    /// </pre>
-    ///
-    /// The returned string is in the form <tt>ns:arrayName[fNS:fieldName='fieldValue']</tt>, where
-    /// "ns" is the prefix for the schema namespace and "fNS" is the prefix for the field namespace.
-    ///
-    /// @param schemaNS The namespace URI for the array; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param fieldNS The namespace URI for the field used as the selector. Same URI and prefix
-    /// usage as the \c schemaNS and \c arrayName parameters.
-    ///
-    /// @param fieldName The name of the field used as the selector. Must be a single XML name, must
-    /// not be null or the empty string. It must be the name of a field that is itself simple.
-    ///
-    /// @param fieldValue The desired value of the field, specified as a null-terminated UTF-8 string.
-    ///
-    /// @param fullPath [out] A string in which to return the composed path.
-
-    static void ComposeFieldSelector ( XMP_StringPtr schemaNS,
-									   XMP_StringPtr arrayName,
-									   XMP_StringPtr fieldNS,
-									   XMP_StringPtr fieldName,
-									   XMP_StringPtr fieldValue,
-									   tStringObj *  fullPath );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ComposeFieldSelector() composes a path expression to select an alternate item by a field's value.
-    ///
-    /// Path syntax allows two forms of "content addressing" to select an item in an array of
-    /// alternatives. The form used in this function lets you select an item in an array of structs
-    /// based on the value of one of the fields in the structs. The other form of content addressing
-    /// is shown in \c ComposeLangSelector().
-    ///
-    /// For example, consider a simple struct that has two fields, the name of a city and the URI of
-    /// an FTP site in that city. Use this to create an array of download alternatives. You can show
-    /// the user a popup built from the values of the city fields, then get the corresponding URI as
-    /// follows:
-    /// <pre>
-    ///   ComposeFieldSelector ( schemaNS, "Downloads", fieldNS, "City", chosenCity, &path );
-    ///   exists = GetStructField ( schemaNS, path, fieldNS, "URI", &uri );
-    /// </pre>
-    ///
-    /// The returned string is in the form <tt>ns:arrayName[fNS:fieldName='fieldValue']</tt>, where
-    /// "ns" is the prefix for the schema namespace and "fNS" is the prefix for the field namespace.
-    ///
-    /// @param schemaNS The namespace URI for the array; see \c GetProperty().
-    ///
-    /// @param arrayName The name of the array. Can be a general path expression, must not be null
-    /// or the empty string; see \c GetProperty() for namespace prefix usage.
-    ///
-    /// @param fieldNS The namespace URI for the field used as the selector. Same URI and prefix
-    /// usage as the \c schemaNS and \c arrayName parameters.
-    ///
-    /// @param fieldName The name of the field used as the selector. Must be a single XML name, must
-    /// not be null or the empty string. It must be the name of a field that is itself simple.
-    ///
-    /// @param fieldValue The desired value of the field, specified as a string object.
-    ///
-    /// @param fullPath [out] A string in which to return the composed path.
-
-    static void ComposeFieldSelector ( XMP_StringPtr      schemaNS,
-									   XMP_StringPtr      arrayName,
-									   XMP_StringPtr      fieldNS,
-									   XMP_StringPtr      fieldName,
-									   const tStringObj & fieldValue,
-									   tStringObj *       fullPath );
-
-    /// @}
-
-    // =============================================================================================
-    /// \name Conversion between binary types and strings
-    /// @{
-    ///
-	///	The main accessors in \c TXMPMeta set and retrieve property values as strings. additional
-	///	functions, such as \c TXMPMeta::SetPropertyInt(), set and retrieve property values as
-	///	explicit binary data types. Use these functions to convert between binary and string
-	///	values.
-	///
-	///	Strings can be specified as null-terminated UTF-8 (\c #XMP_StringPtr), or as string
-	///	objects (\c tStringObj) of the type declared when instantiating the XMP classes; see
-	///	\c XMPSDK.hpp. Alternate forms of each conversion function allow either type of string.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertFromBool() converts a Boolean value to a string.
-    ///
-    /// The string values of Booleans are returned by the macros \c #kXMP_TrueStr and
-    /// \c #kXMP_FalseStr in \c XMP_Const.h.
-    ///
-    /// @param binValue The Boolean value to be converted.
-    ///
-    /// @param strValue [out] A buffer in which to return the string representation of the value.
-
-    static void ConvertFromBool ( bool	       binValue,
-								  tStringObj * strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertFromInt() converts a 32-bit integer value to a string.
-    ///
-    /// @param binValue The integer value to be converted.
-    ///
-    /// @param format Optional. A C \c sprintf format for the conversion. Default is "%d".
-    ///
-    /// @param strValue [out] A buffer in which to return the string representation of the value.
-
-    static void ConvertFromInt ( long	       binValue,
-								 XMP_StringPtr format,
-								 tStringObj *  strValue );
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertFromInt64() converts a 64-bit integer value to a string.
-    ///
-    /// @param binValue The integer value to be converted.
-    ///
-    /// @param format Optional. A C \c sprintf format for the conversion. Default is "%d".
-    ///
-    /// @param strValue [out] A buffer in which to return the string representation of the value.
-
-    static void ConvertFromInt64 ( long long	 binValue,
-								   XMP_StringPtr format,
-								   tStringObj *  strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertFromFloat() converts a floating-point value to a string.
-    ///
-    /// @param binValue The floating-point value to be converted.
-    ///
-    /// @param format Optional. A C \c sprintf format for the conversion. Default is "%d".
-    ///
-    /// @param strValue [out] A buffer in which to return the string representation of the value.
-
-    static void ConvertFromFloat ( double	     binValue,
-								   XMP_StringPtr format,
-								   tStringObj *	 strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertFromDate() converts a date/time value to a string.
-    ///
-    /// Formats a date according to the ISO 8601 profile in http://www.w3.org/TR/NOTE-datetime:
-    /// <pre>
-    ///   YYYY
-    ///   YYYY-MM
-    ///   YYYY-MM-DD
-    ///   YYYY-MM-DDThh:mmTZD
-    ///   YYYY-MM-DDThh:mm:ssTZD
-    ///   YYYY-MM-DDThh:mm:ss.sTZD
-    /// </pre>
-    ///
-    ///  \c YYYY = four-digit year, formatted as "%.4d" <br>
-    ///  \c MM	 = two-digit month (01=January)	<br>
-    ///  \c DD	 = two-digit day of month (01 through 31) <br>
-    ///  \c hh	 = two digits of hour (00 through 23) <br>
-    ///  \c mm	 = two digits of minute (00 through 59)	<br>
-    ///  \c ss	 = two digits of second (00 through 59)	<br>
-    ///  \c s	 = one or more digits representing a decimal fraction of a second <br>
-    ///  \c TZD	 = time zone designator (Z or +hh:mm or -hh:mm)
-    ///
-    /// Time-only input is allowed where the year, month, and day are all zero. This is output as
-    /// "0000-00-00...".
-    ///
-    /// @note ISO 8601 does not allow years less than 1000 or greater than 9999. This API allows
-    /// any year, even negative ones.
-    ///
-    /// @param binValue The date/time value to be converted.
-    ///
-    /// @param strValue [out] A buffer in which to return the ISO 8601 string representation of the date/time.
-
-    static void ConvertFromDate ( const XMP_DateTime & binValue,
-								  tStringObj *	       strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToBool() converts a string to a Boolean value.
-    ///
-    /// The preferred strings are those returned by the macros \c #kXMP_TrueStr and \c #kXMP_FalseStr.
-    /// If these do not match, the function does a case insensitive comparison, then simply 't' or 'f',
-    /// and finally non-zero and zero integer representations.
-    ///
-    /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string.
-    ///
-    /// @return The appropriate C++ bool value for the string.
-
-    static bool ConvertToBool ( XMP_StringPtr strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToBool() converts a string to a Boolean value.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object,
-	/// rather than a <tt>const * char</tt>. It is otherwise identical; see details in the canonical form.
-    ///
-    /// @param strValue The string representation of the value, specified as a string object.
-    ///
-    /// @return The appropriate C++ bool value for the string.
-
-    static bool ConvertToBool ( const tStringObj & strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToInt() converts a string to a 32-bit integer value.
-    ///
-    /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string.
-    ///
-    /// @return The 32-bit integer value.
-
-    static long ConvertToInt ( XMP_StringPtr strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToInt() converts a string to a 32-bit integer value.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object,
-	/// rather than a <tt>const * char</tt>. It is otherwise identical.
-	///
-    /// @param strValue The string representation of the value, specified as a string object.
-    ///
-    /// @return The 32-bit integer value.
-
-    static long ConvertToInt ( const tStringObj & strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToInt64() converts a string to a 64-bit integer value.
-    ///
-    /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string.
-    ///
-    /// @return The 64-bit integer value.
-
-    static long long ConvertToInt64 ( XMP_StringPtr strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToInt64() converts a string to a 64-bit integer value.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object,
-	/// rather than a <tt>const * char</tt>. It is otherwise identical.
-	///
-    /// @param strValue The string representation of the value, specified as a string object.
-    ///
-    /// @return The 64-bit integer value.
-
-    static long long ConvertToInt64 ( const tStringObj & strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToFloat() converts a string to a floating-point value.
-    ///
-    /// @param strValue The string representation of the value, specified as a null-terminated UTF-8 string.
-    ///
-    /// @return The floating-point value.
-
-    static double ConvertToFloat ( XMP_StringPtr strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToFloat() converts a string to a floating-point value.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object,
-	/// rather than a <tt>const * char</tt>. It is otherwise identical.
-	///
-    /// @param strValue The string representation of the value, specified as a string object.
-    ///
-    /// @return The floating-point value.
-
-    static double ConvertToFloat ( const tStringObj & strValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToDate() converts a string to a date/time value.
-    ///
-    /// Parses a date according to the ISO 8601 profile in http://www.w3.org/TR/NOTE-datetime:
-    /// <pre>
-    ///   YYYY
-    ///   YYYY-MM
-    ///   YYYY-MM-DD
-    ///   YYYY-MM-DDThh:mmTZD
-    ///   YYYY-MM-DDThh:mm:ssTZD
-    ///   YYYY-MM-DDThh:mm:ss.sTZD
-    /// </pre>
-    ///
-    ///  \c YYYY = four-digit year, formatted as "%.4d" <br>
-    ///  \c MM	 = two-digit month (01=January)	<br>
-    ///  \c DD	 = two-digit day of month (01 through 31) <br>
-    ///  \c hh	 = two digits of hour (00 through 23) <br>
-    ///  \c mm	 = two digits of minute (00 through 59)	<br>
-    ///  \c ss	 = two digits of second (00 through 59)	<br>
-    ///  \c s	 = one or more digits representing a decimal fraction of a second <br>
-    ///  \c TZD	 = time zone designator (Z or +hh:mm or -hh:mm)
-    ///
-    /// A missing date portion or missing TZD are tolerated. A missing date value can begin with
-    /// "Thh:" or "hh:"; the year, month, and day are all set to zero in the \c #XMP_DateTime value.
-    /// A missing TZD is assumed to be UTC.
-    ///
-    /// @note ISO 8601 does not allow years less than 1000 or greater than 9999. This API allows
-    /// any year, even negative ones.
-    ///
-    /// @param strValue The ISO 8601 string representation of the date/time, specified as a
-    /// null-terminated UTF-8 string.
-    ///
-    /// @param binValue [out] A buffer in which to return the binary date/time value.
-
-    static void ConvertToDate ( XMP_StringPtr  strValue,
-								XMP_DateTime * binValue );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToDate() converts a string to a date/time value.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object,
-	/// rather than a <tt>const * char</tt>. It is otherwise identical.
-	/// See details for the canonical form.
-	///
-    ///
-    /// @param strValue The ISO 8601 string representation of the date/time, specified as a string
-    /// object.
-    ///
-    /// @param binValue [out] A buffer in which to return the binary date/time value.
-
-    static void ConvertToDate ( const tStringObj & strValue,
-								XMP_DateTime *     binValue );
-
-    /// @}
-
-    // =============================================================================================
-    /// \name Date-time manipulation
-    /// @{
-    ///
-	///	In addition to the type-conversion functions that convert between strings and binary
-	///	date-time values, these functions create, manipulate, and compare date-time values.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c CurrentDateTime() obtains the current date and time.
-    ///
-    /// Creates and returns a binary \c #XMP_DateTime value. The returned time is UTC, properly
-    /// adjusted for the local time zone. The resolution of the time is not guaranteed to be finer
-    /// than seconds.
-    ///
-    /// @param time	[out] A buffer in which to return the date/time value.
-
-    static void CurrentDateTime ( XMP_DateTime * time );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SetTimeZone() sets the time zone in a date/time value to the local time zone.
-    ///
-    /// Any existing time zone value is replaced. The other date/time fields are not adjusted in any way.
-    ///
-    /// @param time	A pointer to the date-time value, which is modified in place.
-
-    static void SetTimeZone ( XMP_DateTime * time );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToUTCTime() ensures that a time is UTC.
-    ///
-    /// If the time zone is not UTC, the time is adjusted and the time zone set to be UTC. If the
-    /// time zone is already UTC, the value is not modified.
-    ///
-    /// @param time	A pointer to the date-time value, which is modified in place.
-
-    static void ConvertToUTCTime ( XMP_DateTime * time );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c ConvertToLocalTime() ensures that a time is local.
-    ///
-    /// If the time zone is not the local zone, the time is adjusted and the time zone set to be local.
-    /// If the time zone is already the local zone, the value is not modified.
-    ///
-    /// @param time	A pointer to the date-time value, which is modified in place.
-
-    static void ConvertToLocalTime ( XMP_DateTime * time );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c CompareDateTime() compares the order of two date/time values.
-    ///
-    /// @param left The left-side date/time value.
-    ///
-    /// @param right The right-side date/time value.
-    ///
-    /// @return An integer indicating the order:
-    ///   \li -1 if left is earlier than right
-    ///   \li 0 if left matches right
-    ///   \li +1 if left is later than right
-
-    static int CompareDateTime ( const XMP_DateTime & left,
-								 const XMP_DateTime & right );
-
-    /// @}
-
-    // =============================================================================================
-    /// \name Base64 encoding and decoding
-    /// @{
-    ///
-	/// These functions convert between raw data values and Base64-encoded strings.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c EncodeToBase64() converts a raw data value to a Base64-encoded string.
-    ///
-    /// @param rawStr An \c #XMP_StringPtr (char *) string containing the raw data to be converted.
-    ///
-    /// @param rawLen The number of characters of raw data to be converted.
-    ///
-    /// @param encodedStr [out] A string object in which to return the encoded string.
-
-    static void EncodeToBase64 ( XMP_StringPtr rawStr,
-								 XMP_StringLen rawLen,
-								 tStringObj *  encodedStr );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c EncodeToBase64() converts a raw data value passed in a string object to a Base64-encoded string.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object as input.
-	/// It is otherwise identical.
- 	///
-    /// @param rawStr A string object containing the raw data to be converted.
-    ///
-    /// @param encodedStr [out] A string object in which to return the encoded string.
-
-    static void  EncodeToBase64 ( const tStringObj & rawStr,
-								  tStringObj *       encodedStr );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c  DecodeFromBase64() Decodes a Base64-encoded string to raw data.
-    ///
-    /// @param encodedStr An \c #XMP_StringPtr (char *) string containing the encoded data to be converted.
-    ///
-    /// @param encodedLen The number of characters of raw data to be converted.
-    ///
-    /// @param rawStr [out] A string object in which to return the decoded data.
-
-    static void DecodeFromBase64 ( XMP_StringPtr encodedStr,
-								   XMP_StringLen encodedLen,
-								   tStringObj *  rawStr );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c  DecodeFromBase64() Decodes a Base64-encoded string, passed as a string object, to raw data.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object as input.
-	/// It is otherwise identical.
- 	///
-    /// @param encodedStr An string object containing the encoded data to be converted.
-    ///
-    /// @param rawStr [out] A string object in which to return the decoded data.
-
-    static void DecodeFromBase64 ( const tStringObj & encodedStr,
-								   tStringObj *       rawStr );
-
-    /// @}
-
-    // =============================================================================================
-    // =============================================================================================
-    /// \name JPEG file handling
-    /// @{
-    ///
-    /// These functions support the partitioning of XMP in JPEG files into standard and extended
-    /// portions in order to work around the 64KB size limit of JPEG marker segments.
-    ///
-	/// @note (Doc note) Add detail about how to write out and read back extended data
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c PackageForJPEG() creates XMP serializations appropriate for a JPEG file.
-    ///
-    /// The standard XMP in a JPEG file is limited to 64K bytes. This function serializes the XMP
-    /// metadata in an XMP object into a string of RDF (see \c TXMPMeta::SerializeToBuffer()). If
-    /// the data does not fit into the 64K byte limit, it creates a second packet string with the
-    /// extended data.
-    ///
-    /// @param xmpObj The XMP object containing the metadata.
-    ///
-    /// @param standardXMP [out] A string object in which to return the full standard XMP packet.
-    ///
-    /// @param extendedXMP [out] A string object in which to return the serialized extended XMP,
-    /// empty if not needed.
-    ///
-    /// @param extendedDigest [out] A string object in which to return an MD5 digest of the serialized
-    /// extended XMP, empty if not needed.
-    ///
-    /// @see \c MergeFromJPEG()
-
-    static void PackageForJPEG ( const TXMPMeta<tStringObj> & xmpObj,
-								 tStringObj *                 standardXMP,
-								 tStringObj *                 extendedXMP,
-								 tStringObj *                 extendedDigest );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c MergeFromJPEG() merges standard and extended XMP retrieved from a JPEG file.
-    ///
-    /// When an extended partition stores properties that do not fit into the JPEG file limitation
-    /// of 64K bytes, this function integrates those properties back into the same XMP object with
-    /// those from the standard XMP packet.
-    ///
-    /// @param fullXMP [in, out] An XMP object which the caller has initialized from the standard
-    /// XMP packet in a JPEG file. The extended XMP is added to this object.
-    ///
-    /// @param extendedXMP An XMP object which the caller has initialized from the extended XMP
-    /// packet in a JPEG file.
-    ///
-    /// @see \c PackageForJPEG()
-
-    static void MergeFromJPEG ( TXMPMeta<tStringObj> *       fullXMP,
-								const TXMPMeta<tStringObj> & extendedXMP );
-
-    /// @}
-
-    // =============================================================================================
-    /// \name Editing utilities
-    /// @{
-    ///
-    /// These functions are useful in implementing a user interface for editing XMP. They
-	/// convert sets of property values to and from displayable and manipulable strings, and perform
-	/// operations on sets of metadata, such as those available from the File Info dialog box.
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c CatenateArrayItems() creates a single edit string from a set of array item values.
-    ///
-    /// Collects the values of all items in an array into a single string, using a specified
-    /// separation string. Each item in the specified array must be a simple string value.
-    ///
-    /// @param xmpObj The XMP object containing the array to be catenated.
-    ///
-    /// @param schemaNS The schema namespace URI for the array. Must not be null or the empty string.
-    ///
-    /// @param arrayName The name of the array. May be a general path expression, must not be null
-    /// or the empty string.
-    ///
-    /// @param separator The string with which to separate the items in the catenated string.
-    /// Defaults to "; ", ASCII semicolon and space (U+003B, U+0020).
-    ///
-    /// @param quotes The character or characters to use as quotes around array items that contain a
-    /// separator. Defaults to the double-quote character ("), ASCII quote (U+0022).
-    ///
-    /// @param options Option flags to control the catenation. <<what options?>>
-    ///
-    /// @param catedStr [out] A string object in which to return the catenated array items.
-    ///
-    /// @see \c SeparateArrayItems()
-
-    static void CatenateArrayItems ( const TXMPMeta<tStringObj> & xmpObj,
-									 XMP_StringPtr                schemaNS,
-									 XMP_StringPtr                arrayName,
-									 XMP_StringPtr                separator,
-									 XMP_StringPtr                quotes,
-									 XMP_OptionBits               options,
-									 tStringObj *                 catedStr );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SeparateArrayItems() updates an array from a concatenated edit string of values.
-    ///
-    /// This reverses the action of \c CatenateArrayItems(), separating out individual array items
-    /// from the edit string and updating the array with the new values. Each item in the array must
-    /// be a simple string value.
-    ///
-    /// @param xmpObj The XMP object containing the array to be updated.
-    ///
-    /// @param schemaNS The schema namespace URI for the array. Must not be null or the empty string.
-    ///
-    /// @param arrayName The name of the array. May be a general path expression, must not be null
-    /// or the empty string.
-    ///
-    /// @param options Option flags to control the separation. <<what options?>>
-    ///
-    /// @param catedStr The concatenated array items, as created by \c CatenateArrayItems(),
-    /// specified as a null-terminated UTF-8 string.
-
-    static void SeparateArrayItems ( TXMPMeta<tStringObj> * xmpObj,
-									 XMP_StringPtr          schemaNS,
-									 XMP_StringPtr          arrayName,
-									 XMP_OptionBits         options,
-									 XMP_StringPtr          catedStr );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c SeparateArrayItems() updates an array from a concatenated edit string of values.
-    ///
-    /// Overloads the basic form of the function, allowing you to pass a string object in which
-    ///	to return the concatenated string. It is otherwise identical; see details for the canonical form.
- 	///
-
-    static void SeparateArrayItems ( TXMPMeta<tStringObj> * xmpObj,
-									 XMP_StringPtr          schemaNS,
-									 XMP_StringPtr          arrayName,
-									 XMP_OptionBits         options,
-									 const tStringObj &     catedStr );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c  RemoveProperties() removes multiple properties from an XMP object.
-    ///
-    /// The operation depends on how the namespace and property are specified:
-    ///
-    ///   \li Non-empty \c schemaNS and \c propName - The named property is removed if it is an
-    ///   external property, or if the \c #kXMPUtil_DoAllProperties option flag is set. It does not
-    ///   matter whether the named property is an actual property or an alias.
-    ///
-    ///   \li Non-empty \c schemaNS and empty \c propName - All external properties in the named
-    ///   schema are removed. Internal properties are also removed if the
-    ///   \c #kXMPUtil_DoAllProperties option flag is set. In addition, aliases from the named schema
-    ///   are removed if the \c #kXMPUtil_IncludeAliases option flag is set.
-    ///
-    ///   \li Empty \c schemaNS and empty \c propName - All external properties in all schemas are
-    ///   removed. Internal properties are also removed if the \c #kXMPUtil_DoAllProperties option
-    ///   flag is set. Aliases are handled implicitly, because the associated actuals are removed or
-    ///   not.
-    ///
-    ///   \li It is an error to pass an empty \c schemaNS and non-empty \c propName.
-    ///
-    /// @param xmpObj The XMP object containing the properties to be removed.
-    ///
-    /// @param schemaNS Optional schema namespace URI for the properties to be removed.
-    ///
-    /// @param propName Optional path expression for the property to be removed.
-    ///
-    /// @param options Option flags to control the deletion operation. A logical OR of these
-    /// bit-flag constants:
-    ///   \li \c #kXMPUtil_DoAllProperties - Delete internal properties in addition to external properties.
-    ///   \li \c #kXMPUtil_IncludeAliases - Include aliases if the schema is explicitly specified.
-
-    static void RemoveProperties ( TXMPMeta<tStringObj> * xmpObj,
-								   XMP_StringPtr          schemaNS = 0,
-								   XMP_StringPtr          propName = 0,
-								   XMP_OptionBits         options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c AppendProperties() adds or moves properties from one XMP object to another.
-    ///
-    /// The default operation is to append only external properties that do not already exist in the
-    /// destination. Option flags allow you to	add internal properties, and to merge values of
-    /// properties that exist in both the source and destination.
-    ///
-    ///   \li \c #kXMPUtil_DoAllProperties: Operate on all top-level properties, external and
-    ///   internal. You can use this flag together with \c #kXMPUtil_ReplaceOldValues to replace the
-    ///   values of existing top-level properties.
-    ///
-    ///   \li \c #kXMPUtil_ReplaceOldValues: Propagate all top-level properties from the source to
-    ///   the destination, replacing any existing values. The values of properties in the
-    ///   destination that are not in the source are not modified.<br>
-    ///   The keep-or-replace-old notion also applies within structs and arrays. Top-level
-    ///   properties are added to the destination if they do not already exist. If they do exist but
-    ///   differ in form (simple/struct/array) then the destination is not modified. If the forms
-    ///   match, simple properties are left unchanged, while structs and arrays are merged.<br>
-    ///   Do not use this option when the processing is more complicated. <<than what??>>
-    ///
-    ///   \li \c #kXMPUtil_DeleteEmptyValues: An empty value in the source XMP causes the
-    ///   corresponding destination property to be deleted. By default, empty values are treated in
-    ///   the same way as non-empty values. An empty value is a simple empty string, an array with
-    ///   no items,or a struct with no fields. Qualifiers are ignored.
-    ///
-    /// The detailed behavior is defined by the following pseudo-code:
-    ///
-    /// <pre>
-    /// AppendProperties ( sourceXMP, destXMP, options ):
-    ///    doAll = options & kXMPUtil_DoAllProperties
-    ///    replaceOld = options & kXMPUtil_ReplaceOldValues
-    ///    deleteEmpty = options & kXMPUtil_DeleteEmptyValues
-    ///    for all source schema (top level namespaces):
-    ///    for all top level properties in sourceSchema:
-    ///    if doAll or prop is external:
-    ///       AppendSubtree ( sourceNode, destSchema, replaceOld, deleteEmpty )
-    ///
-    /// AppendSubtree ( sourceNode, destParent, replaceOld, deleteEmpty ):
-    ///    if deleteEmpty and source value is empty:
-    ///       delete the corresponding child from destParent
-    ///    else if sourceNode not in destParent (by name):
-    ///       copy sourceNode's subtree to destParent
-    ///    else if replaceOld:
-    ///       delete subtree from destParent
-    ///       copy sourceNode's subtree to destParent
-    ///    else: // (Already exists in dest and not replacing, merge structs and arrays)
-    ///       if sourceNode and destNode forms differ:
-    ///          return, leave the destNode alone
-    ///       else if form is a struct:
-    ///          for each field in sourceNode:
-    ///             AppendSubtree ( sourceNode.field, destNode, replaceOld )
-    ///       else if form is an alt-text array:
-    ///          copy new items by xml:lang value into the destination
-    ///       else if form is an array:
-    ///          copy new items by value into the destination, ignoring order and duplicates
-    /// </pre>
-    ///
-    /// Array item checking is n-squared; this can be time-intensive if the replace-old options is
-    /// not specified. Each source item is checked to see if it already exists in the destination,
-    /// without regard to order or duplicates. Simple items are compared by value and \c xml:lang
-    /// qualifier; other qualifiers are ignored. Structs are recursively compared by field names,
-    /// without regard to field order. Arrays are compared by recursively comparing all items.
-    ///
-    /// @param source The source XMP object.
-    ///
-    /// @param dest The destination XMP object.
-    ///
-    /// @param options Option flags to control the copying.	A logical OR of these bit-flag constants:
-    ///   \li \c kXMPUtil_DoAllProperties - Operate on internal properties in addition to external properties.
-    ///   \li \c kXMPUtil_ReplaceOldValues - Replace the values of existing properties.
-    ///   \li \c kXMPUtil_DeleteEmptyValues - Delete properties if the new value is empty.
-
-    static void AppendProperties ( const TXMPMeta<tStringObj> & source,
-								   TXMPMeta<tStringObj> *       dest,
-								   XMP_OptionBits               options = 0 );
-
-    // ---------------------------------------------------------------------------------------------
-    /// @brief \c DuplicateSubtree() replicates a subtree from one XMP object into another.
-    ///
-    /// The destination can be a different namespace and root location in the same object, or the
-    /// same or a different location in another XMP object.
-    ///
-    /// @param source The source XMP object.
-    ///
-    /// @param dest The destination XMP object.
-    ///
-    /// @param sourceNS The schema namespace URI for the source subtree.
-    ///
-    /// @param sourceRoot The root location for the source subtree. Can be a general path expression,
-    /// must not be null or the empty string.
-    ///
-    /// @param destNS The schema namespace URI for the destination. Defaults to the source namespace.
-    ///
-    /// @param destRoot The root location for the destination. Can be a general path expression.
-    /// Defaults to the source location.
-    ///
-    /// @param options Option flags to control the operation. <<options?>>
-
-    static void DuplicateSubtree ( const TXMPMeta<tStringObj> & source,
-								   TXMPMeta<tStringObj> *       dest,
-								   XMP_StringPtr                sourceNS,
-								   XMP_StringPtr                sourceRoot,
-								   XMP_StringPtr                destNS = 0,
-								   XMP_StringPtr                destRoot = 0,
-								   XMP_OptionBits               options = 0 );
-
-    /// @}
-
-    // =============================================================================================
-
-    // =============================================================================================
-
-};  // class TXMPUtils
-
-// =================================================================================================
-
-#endif // __TXMPUtils_hpp__
diff --git a/xmpsdk/include/XMP.incl_cpp b/xmpsdk/include/XMP.incl_cpp
deleted file mode 100644
index 6501be9c..00000000
--- a/xmpsdk/include/XMP.incl_cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef __XMP_incl_cpp__
-#define __XMP_incl_cpp__ 1
-
-// =================================================================================================
-// ADOBE SYSTEMS INCORPORATED
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved
-//
-// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-//  ================================================================================================
-/// \file XMP.incl_cpp
-/// \brief Overall client glue file for the XMP toolkit.
-///
-/// This is an overall client source file of XMP toolkit glue, the only XMP-specific one that
-/// clients should build in projects. This ensures that all of the client-side glue code for the
-/// XMP toolkit gets compiled.
-///
-/// You cannot compile this file directly, because the template's string type must be declared and 
-/// only the client can do that. Instead, include this in some other source file. For example, 
-/// to use <tt>std::string</tt> you only need these two lines:
-///
-/// \code
-///  #include <string>
-///  #include "XMP.incl_cpp"
-/// \endcode
-
-
-#include "XMPSDK.hpp" // ! This must be the first include!
-
-#define XMP_ClientBuild 1
-
-#ifdef _MSC_VER
-    #if XMP_DebugBuild
-        #pragma warning ( push, 4 )
-    #else
-        #pragma warning ( push, 3 )
-    #endif
-    #pragma warning ( disable : 4189 ) // local variable is initialized but not referenced
-    #pragma warning ( disable : 4702 ) // unreachable code
-    #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning)
-#endif
-
-#if defined ( TXMP_STRING_TYPE ) && (! TXMP_EXPAND_INLINE)
-
-    // We're using a single out of line instantiation. Do it here.
-
-    #include "client-glue/TXMPMeta.incl_cpp"
-    #include "client-glue/TXMPIterator.incl_cpp"
-    #include "client-glue/TXMPUtils.incl_cpp"
-    template class TXMPMeta <TXMP_STRING_TYPE>;
-    template class TXMPIterator <TXMP_STRING_TYPE>;
-    template class TXMPUtils <TXMP_STRING_TYPE>;
-
-#endif
-
-#ifdef _MSC_VER
-    #pragma warning ( pop )
-#endif
-
-#endif // __XMP_incl_cpp__
diff --git a/xmpsdk/include/XMPSDK.hpp b/xmpsdk/include/XMPSDK.hpp
deleted file mode 100644
index 229714f8..00000000
--- a/xmpsdk/include/XMPSDK.hpp
+++ /dev/null
@@ -1,89 +0,0 @@
-#ifndef __XMP_hpp__
-#define __XMP_hpp__ 1
-
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-//  ================================================================================================
-/// \file XMPSDK.hpp
-/// \brief Overall header file for the XMP Toolkit
-///
-/// This is an overall header file, the only one that C++ clients should include.
-///
-/// The full client API is in the \c TXMPMeta.hpp, \c TXMPIterator.hpp, \c TXMPUtils.hpp headers.
-/// Read these for information, but do not include them directly. The \c TXMP... classes are C++
-/// template classes that must be instantiated with a string class such as \c std::string. The
-/// string class is used to return text strings for property values, serialized XMP, and so on.
-/// Clients must also compile \c XMP.incl_cpp to ensure that all client-side glue code is generated.
-/// This should be done by including it in exactly one client source file.
-///
-/// There are two C preprocessor macros that simplify use of the templates:
-///
-/// \li \c TXMP_STRING_TYPE - Define this as the string class to use with the template. You will get
-/// the template headers included and typedefs (\c SXMPMeta, and so on) to use in your code.
-///
-/// \li \c TXMP_EXPAND_INLINE - Define this as 1 if you want to have the template functions expanded
-/// inline in your code. Leave it undefined, or defined as 0, to use out-of-line instantiations of
-/// the template functions. Compiling \c XMP.incl_cpp generates explicit out-of-line
-/// instantiations if \c TXMP_EXPAND_INLINE is off.
-///
-/// The template parameter, class \c tStringObj, must have the following member functions (which
-/// match those for \c std::string):
-///
-/// <pre>
-///  tStringObj& assign ( const char * str, size_t len )
-///  size_t size() const
-///  const char * c_str() const
-/// </pre>
-///
-/// The string class must be suitable for at least UTF-8. This is the encoding used for all general
-/// values, and is the default encoding for serialized XMP. The string type must also be suitable
-/// for UTF-16 or UTF-32 if those serialization encodings are used. This mainly means tolerating
-/// embedded 0 bytes, which \c std::string does.
-//  ================================================================================================
-
-/// /c XMP_Environment.h must be the first included header.
-#include "XMP_Environment.h"
-
-#include "XMP_Version.h"
-#include "XMP_Const.h"
-
-#ifdef _MSC_VER
-    #if XMP_DebugBuild
-        #pragma warning ( push, 4 )
-    #else
-        #pragma warning ( push, 3 )
-    #endif
-    #pragma warning ( disable : 4702 ) // unreachable code
-    #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning)
-#endif
-
-#if defined ( TXMP_STRING_TYPE )
-
-    #include "TXMPMeta.hpp"
-    #include "TXMPIterator.hpp"
-    #include "TXMPUtils.hpp"
-    typedef class TXMPMeta <TXMP_STRING_TYPE>     SXMPMeta;       // For client convenience.
-    typedef class TXMPIterator <TXMP_STRING_TYPE> SXMPIterator;
-    typedef class TXMPUtils <TXMP_STRING_TYPE>    SXMPUtils;
-    #if TXMP_EXPAND_INLINE
-    	#error "TXMP_EXPAND_INLINE is not working at present. Please don't use it."
-        #include "client-glue/TXMPMeta.incl_cpp"
-        #include "client-glue/TXMPIterator.incl_cpp"
-        #include "client-glue/TXMPUtils.incl_cpp"
-    #endif
-
-#endif  // TXMP_STRING_TYPE
-
-#ifdef _MSC_VER
-    #pragma warning ( pop )
-#endif
-
-// =================================================================================================
-
-#endif  // __XMP_hpp__
diff --git a/xmpsdk/include/XMP_Const.h b/xmpsdk/include/XMP_Const.h
deleted file mode 100644
index 03161888..00000000
--- a/xmpsdk/include/XMP_Const.h
+++ /dev/null
@@ -1,1330 +0,0 @@
-#ifndef __XMP_Const_h__
-#define __XMP_Const_h__ 1
-
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"
-
-   #include <stddef.h>
-
-#if XMP_MacBuild	// ! No stdint.h on Windows and some UNIXes.
-    #include <stdint.h>
-#endif
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// =================================================================================================
-/// \file XMP_Const.h
-/// \brief Common C/C++ types and constants for the XMP toolkit.
-// =================================================================================================
-
-// =================================================================================================
-// Basic types and constants
-// =========================
-
-// The XMP_... types are used on the off chance that the ..._t types present a problem. In that
-// case only the declarations of the XMP_... types needs to change, not all of the uses. These
-// types are used where fixed sizes are required in order to have a known ABI for a DLL build.
-
-#if XMP_MacBuild
-
-    typedef int8_t   XMP_Int8;
-    typedef int16_t  XMP_Int16;
-    typedef int32_t  XMP_Int32;
-    typedef int64_t  XMP_Int64;
-
-    typedef uint8_t  XMP_Uns8;
-    typedef uint16_t XMP_Uns16;
-    typedef uint32_t XMP_Uns32;
-    typedef uint64_t XMP_Uns64;
-
-#else
-
-    typedef signed char XMP_Int8;
-    typedef signed short XMP_Int16;
-    typedef signed long XMP_Int32;
-    typedef signed long long XMP_Int64;
-
-    typedef unsigned char XMP_Uns8;
-    typedef unsigned short XMP_Uns16;
-    typedef unsigned long XMP_Uns32;
-    typedef unsigned long long XMP_Uns64;
-
-#endif
-
-typedef XMP_Uns8 XMP_Bool;
-
-/// An "ABI safe" pointer to the internal part of an XMP object. Use to pass an XMP object across
-/// client DLL boundaries. See \c TXMPMeta::GetInternalRef().
-typedef struct __XMPMeta__ *        XMPMetaRef;
-
-/// An "ABI safe" pointer to the internal part of an XMP iteration object. Use to pass an XMP
-/// iteration object across client DLL boundaries. See \c TXMPIterator.
-typedef struct __XMPIterator__ *    XMPIteratorRef;
-
-/// An "ABI safe" pointer to the internal part of an XMP document operations object. Use to pass an
-/// XMP document operations object across client DLL boundaries. See \c TXMPDocOps.
-typedef struct __XMPDocOps__ *    XMPDocOpsRef;
-
-/// An "ABI safe" pointer to the internal part of an XMP file-handling object. Use to pass an XMP
-/// file-handling object across  client DLL boundaries. See \c TXMPFiles.
-typedef struct __XMPFiles__ *       XMPFilesRef;
-
-// =================================================================================================
-
-/// \name General scalar types and constants
-/// @{
-
-/// \typedef XMP_StringPtr
-/// \brief The type for input string parameters. A <tt>const char *</tt>, a null-terminated UTF-8
-/// string.
-
-/// \typedef XMP_StringLen
-/// \brief The type for string length parameters. A 32-bit unsigned integer, as big as will be
-/// practically needed.
-
-/// \typedef XMP_Index
-/// \brief The type for offsets and indices. A 32-bit signed integer. It is signed to allow -1 for
-/// loop termination.
-
-/// \typedef XMP_OptionBits
-/// \brief The type for a collection of 32 flag bits. Individual flags are defined as enum value bit
-/// masks; see \c #kXMP_PropValueIsURI and following. A number of macros provide common set or set
-/// operations, such as \c XMP_PropIsSimple. For other tests use an expression like <code>options &
-/// kXMP_<theOption></code>. When passing multiple option flags use the bitwise-OR operator. '|',
-/// not the arithmatic plus, '+'.
-
-typedef const char * XMP_StringPtr;  // Points to a null terminated UTF-8 string.
-typedef XMP_Uns32    XMP_StringLen;
-typedef XMP_Int32    XMP_Index;      // Signed, sometimes -1 is handy.
-typedef XMP_Uns32    XMP_OptionBits; // Used as 32 individual bits.
-
-/// \def kXMP_TrueStr
-/// \brief The canonical true string value for Booleans in serialized XMP.
-///
-/// Code that converts from string to bool should be case insensitive, and also allow "1".
-
-/// \def kXMP_FalseStr
-/// \brief The canonical false string value for Booleans in serialized XMP.
-///
-/// Code that converts	from string to bool should be case insensitive, and also allow "0".
-
-#define kXMP_TrueStr  "True"  // Serialized XMP spellings, not for the type bool.
-#define kXMP_FalseStr "False"
-
-/// Type for yes/no/maybe answers. The values are picked to allow Boolean-like usage. The yes and
-/// values are true (non-zero), the no value is false (zero).
-enum {
-	/// The part or parts have definitely changed.
-	kXMPTS_Yes = 1,
-	/// The part or parts have definitely not changed.
-	kXMPTS_No = 0,
-	/// The part or parts might, or might not, have changed.
-	kXMPTS_Maybe = -1
-};
-typedef XMP_Int8 XMP_TriState;
-
-/// @}
-
-// =================================================================================================
-
-/// \struct XMP_DateTime
-/// \brief The expanded type for a date and time.
-///
-/// Dates and time in the serialized XMP are ISO 8601 strings. The \c XMP_DateTime struct allows
-/// easy conversion with other formats.
-///
-/// All of the fields are 32 bit, even though most could be 8 bit. This avoids overflow when doing
-/// carries for arithmetic or normalization. All fields have signed values for the same reasons.
-///
-/// Date-time values are occasionally used with only a date or only a time component. A date without
-/// a time has zeros in the \c XMP_DateTime struct for all time fields. A time without a date has
-/// zeros for all date fields (year, month, and day).
-///
-/// \c TXMPUtils provides utility functions for manipulating date-time values.
-///
-/// @see \c TXMPUtils::ConvertToDate(), \c TXMPUtils::ConvertFromDate(),
-/// \c TXMPUtils::CompareDateTime(), \c TXMPUtils::ConvertToLocalTime(),
-/// \c TXMPUtils::ConvertToUTCTime(), \c TXMPUtils::CurrentDateTime(),
-/// \c TXMPUtils::SetTimeZone()
-
-struct XMP_DateTime {
-
-	/// The year, can be negative.
-    XMP_Int32 year;
-
-	/// The month in the range 1..12.
-    XMP_Int32 month;
-
-	/// The day of the month in the range 1..31.
-    XMP_Int32 day;
-
-	/// The hour in the range 0..23.
-    XMP_Int32 hour;
-
-	/// The minute in the range 0..59.
-    XMP_Int32 minute;
-
-	/// The second in the range 0..59.
-    XMP_Int32 second;
-
-	/// The "sign" of the time zone, \c #kXMP_TimeIsUTC (0) means UTC, \c #kXMP_TimeWestOfUTC (-1)
-	/// is west, \c #kXMP_TimeEastOfUTC (+1) is east.
-    XMP_Int32 tzSign;
-
-	/// The time zone hour in the range 0..23.
-    XMP_Int32 tzHour;
-
-	/// The time zone minute in the range 0..59.
-    XMP_Int32 tzMinute;
-
-	/// Nanoseconds within a second, often left as zero.
-    XMP_Int32 nanoSecond;
-
-};
-
-/// Constant values for \c XMP_DateTime::tzSign field.
-enum {
-	/// Time zone is west of UTC.
-    kXMP_TimeWestOfUTC = -1,
-	/// UTC time.
-    kXMP_TimeIsUTC     =  0,
-	/// Time zone is east of UTC.
-    kXMP_TimeEastOfUTC = +1
-};
-
-// =================================================================================================
-// Standard namespace URI constants
-// ================================
-
-/// \name XML namespace constants for standard XMP schema.
-/// @{
-///
-/// \def kXMP_NS_XMP
-/// \brief The XML namespace for the XMP "basic" schema.
-///
-/// \def kXMP_NS_XMP_Rights
-/// \brief The XML namespace for the XMP copyright schema.
-///
-/// \def kXMP_NS_XMP_MM
-/// \brief The XML namespace for the XMP digital asset management schema.
-///
-/// \def kXMP_NS_XMP_BJ
-/// \brief The XML namespace for the job management schema.
-///
-/// \def kXMP_NS_XMP_T
-/// \brief The XML namespace for the XMP text document schema.
-///
-/// \def kXMP_NS_XMP_T_PG
-/// \brief The XML namespace for the XMP paged document schema.
-///
-/// \def kXMP_NS_PDF
-/// \brief The XML namespace for the PDF schema.
-///
-/// \def kXMP_NS_Photoshop
-/// \brief The XML namespace for the Photoshop custom schema.
-///
-/// \def kXMP_NS_EXIF
-/// \brief The XML namespace for Adobe's EXIF schema.
-///
-/// \def kXMP_NS_TIFF
-/// \brief The XML namespace for Adobe's TIFF schema.
-///
-/// @}
-
-#define kXMP_NS_XMP        "http://ns.adobe.com/xap/1.0/"
-
-#define kXMP_NS_XMP_Rights "http://ns.adobe.com/xap/1.0/rights/"
-#define kXMP_NS_XMP_MM     "http://ns.adobe.com/xap/1.0/mm/"
-#define kXMP_NS_XMP_BJ     "http://ns.adobe.com/xap/1.0/bj/"
-
-#define kXMP_NS_PDF        "http://ns.adobe.com/pdf/1.3/"
-#define kXMP_NS_Photoshop  "http://ns.adobe.com/photoshop/1.0/"
-#define kXMP_NS_PSAlbum    "http://ns.adobe.com/album/1.0/"
-#define kXMP_NS_EXIF       "http://ns.adobe.com/exif/1.0/"
-#define kXMP_NS_EXIF_Aux   "http://ns.adobe.com/exif/1.0/aux/"
-#define kXMP_NS_TIFF       "http://ns.adobe.com/tiff/1.0/"
-#define kXMP_NS_PNG        "http://ns.adobe.com/png/1.0/"
-#define kXMP_NS_SWF        "http://ns.adobe.com/swf/1.0/"
-#define kXMP_NS_JPEG       "http://ns.adobe.com/jpeg/1.0/"
-#define kXMP_NS_JP2K       "http://ns.adobe.com/jp2k/1.0/"
-#define kXMP_NS_CameraRaw  "http://ns.adobe.com/camera-raw-settings/1.0/"
-#define kXMP_NS_DM         "http://ns.adobe.com/xmp/1.0/DynamicMedia/"
-#define kXMP_NS_ASF        "http://ns.adobe.com/asf/1.0/"
-#define kXMP_NS_WAV        "http://ns.adobe.com/xmp/wav/1.0/"
-
-#define kXMP_NS_XMP_Note   "http://ns.adobe.com/xmp/note/"
-
-#define kXMP_NS_AdobeStockPhoto "http://ns.adobe.com/StockPhoto/1.0/"
-#define kXMP_NS_CreatorAtom "http://ns.adobe.com/creatorAtom/1.0/"
-
-/// \name XML namespace constants for qualifiers and structured property fields.
-/// @{
-///
-/// \def kXMP_NS_XMP_IdentifierQual
-/// \brief The XML namespace for qualifiers of the xmp:Identifier property.
-///
-/// \def kXMP_NS_XMP_Dimensions
-/// \brief The XML namespace for fields of the Dimensions type.
-///
-/// \def kXMP_NS_XMP_Image
-/// \brief The XML namespace for fields of a graphical image. Used for the Thumbnail type.
-///
-/// \def kXMP_NS_XMP_ResourceEvent
-/// \brief The XML namespace for fields of the ResourceEvent type.
-///
-/// \def kXMP_NS_XMP_ResourceRef
-/// \brief The XML namespace for fields of the ResourceRef type.
-///
-/// \def kXMP_NS_XMP_ST_Version
-/// \brief The XML namespace for fields of the Version type.
-///
-/// \def kXMP_NS_XMP_ST_Job
-/// \brief The XML namespace for fields of the JobRef type.
-///
-/// @}
-
-#define kXMP_NS_XMP_IdentifierQual "http://ns.adobe.com/xmp/Identifier/qual/1.0/"
-#define kXMP_NS_XMP_Dimensions     "http://ns.adobe.com/xap/1.0/sType/Dimensions#"
-#define kXMP_NS_XMP_Text           "http://ns.adobe.com/xap/1.0/t/"
-#define kXMP_NS_XMP_PagedFile      "http://ns.adobe.com/xap/1.0/t/pg/"
-#define kXMP_NS_XMP_Graphics       "http://ns.adobe.com/xap/1.0/g/"
-#define kXMP_NS_XMP_Image          "http://ns.adobe.com/xap/1.0/g/img/"
-#define kXMP_NS_XMP_Font           "http://ns.adobe.com/xap/1.0/sType/Font#"
-#define kXMP_NS_XMP_ResourceEvent  "http://ns.adobe.com/xap/1.0/sType/ResourceEvent#"
-#define kXMP_NS_XMP_ResourceRef    "http://ns.adobe.com/xap/1.0/sType/ResourceRef#"
-#define kXMP_NS_XMP_ST_Version     "http://ns.adobe.com/xap/1.0/sType/Version#"
-#define kXMP_NS_XMP_ST_Job         "http://ns.adobe.com/xap/1.0/sType/Job#"
-#define kXMP_NS_XMP_ManifestItem   "http://ns.adobe.com/xap/1.0/sType/ManifestItem#"
-
-// Deprecated XML namespace constants
-#define kXMP_NS_XMP_T     "http://ns.adobe.com/xap/1.0/t/"
-#define kXMP_NS_XMP_T_PG  "http://ns.adobe.com/xap/1.0/t/pg/"
-#define kXMP_NS_XMP_G_IMG "http://ns.adobe.com/xap/1.0/g/img/"
-
-/// \name XML namespace constants from outside Adobe.
-/// @{
-///
-/// \def kXMP_NS_DC
-/// \brief The XML namespace for the Dublin Core schema.
-///
-/// \def kXMP_NS_IPTCCore
-/// \brief The XML namespace for the IPTC Core schema.
-///
-/// \def kXMP_NS_RDF
-/// \brief The XML namespace for RDF.
-///
-/// \def kXMP_NS_XML
-/// \brief The XML namespace for XML.
-///
-/// @}
-
-#define kXMP_NS_DC              "http://purl.org/dc/elements/1.1/"
-
-#define kXMP_NS_IPTCCore       "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/"
-
-#define kXMP_NS_DICOM          "http://ns.adobe.com/DICOM/"
-
-#define kXMP_NS_PDFA_Schema    "http://www.aiim.org/pdfa/ns/schema#"
-#define kXMP_NS_PDFA_Property  "http://www.aiim.org/pdfa/ns/property#"
-#define kXMP_NS_PDFA_Type      "http://www.aiim.org/pdfa/ns/type#"
-#define kXMP_NS_PDFA_Field     "http://www.aiim.org/pdfa/ns/field#"
-#define kXMP_NS_PDFA_ID        "http://www.aiim.org/pdfa/ns/id/"
-#define kXMP_NS_PDFA_Extension "http://www.aiim.org/pdfa/ns/extension/"
-
-#define kXMP_NS_PDFX           "http://ns.adobe.com/pdfx/1.3/"
-#define	kXMP_NS_PDFX_ID        "http://www.npes.org/pdfx/ns/id/"
-
-#define kXMP_NS_RDF            "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
-#define kXMP_NS_XML            "http://www.w3.org/XML/1998/namespace"
-
-// =================================================================================================
-// Enums and macros used for option bits
-// =====================================
-
-/// \name Macros for standard option selections.
-/// @{
-///
-/// \def kXMP_ArrayLastItem
-/// \brief Options macro accesses last array item.
-///
-/// \def kXMP_UseNullTermination
-/// \brief Options macro sets string style.
-///
-/// \def kXMP_NoOptions
-/// \brief Options macro clears all property-type bits.
-///
-/// @}
-
-#define kXMP_ArrayLastItem      ((XMP_Index)(-1L))
-#define kXMP_UseNullTermination ((XMP_StringLen)(~0UL))
-#define kXMP_NoOptions          ((XMP_OptionBits)0UL)
-
-/// \name Macros for setting and testing general option bits.
-/// @{
-///
-/// \def XMP_SetOption
-/// \brief Macro sets an option flag bit.
-///	\param var A variable storing an options flag.
-/// \param opt The bit-flag constant to set.
-///
-/// \def XMP_ClearOption
-/// \brief Macro clears an option flag bit.
-///	\param var A variable storing an options flag.
-/// \param opt The bit-flag constant to clear.
-///
-/// \def XMP_TestOption
-/// \brief Macro reports whether an option flag bit is set.
-///	\param var A variable storing an options flag.
-/// \param opt The bit-flag constant to test.
-/// \return True if the bit is set.
-///
-/// \def XMP_OptionIsSet
-/// \brief Macro reports whether an option flag bit is set.
-///	\param var A variable storing an options flag.
-/// \param opt The bit-flag constant to test.
-/// \return True if the bit is set.
-///
-/// \def XMP_OptionIsClear
-/// \brief Macro reports whether an option flag bit is clear.
-///	\param var A variable storing an options flag.
-/// \param opt The bit-flag constant to test.
-/// \return True if the bit is clear.
-///
-/// @}
-
-#define XMP_SetOption(var,opt)      var |= (opt)
-#define XMP_ClearOption(var,opt)    var &= ~(opt)
-#define XMP_TestOption(var,opt)     (((var) & (opt)) != 0)
-#define XMP_OptionIsSet(var,opt)    (((var) & (opt)) != 0)
-#define XMP_OptionIsClear(var,opt)  (((var) & (opt)) == 0)
-
-/// \name Macros for setting and testing specific option bits.
-/// @{
-///
-/// \def XMP_PropIsSimple
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_PropIsStruct
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_PropIsArray
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_ArrayIsUnordered
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_ArrayIsOrdered
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_ArrayIsAlternate
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_ArrayIsAltText
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_PropHasQualifiers
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_PropIsQualifier
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_PropHasLang
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_NodeIsSchema
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// \def XMP_PropIsAlias
-/// \brief Macro reports the property type specified by an options flag.
-/// \param opt The options flag to check.
-///
-/// @}
-
-#define XMP_PropIsSimple(opt)       (((opt) & kXMP_PropCompositeMask) == 0)
-#define XMP_PropIsStruct(opt)       (((opt) & kXMP_PropValueIsStruct) != 0)
-#define XMP_PropIsArray(opt)        (((opt) & kXMP_PropValueIsArray) != 0)
-
-#define XMP_ArrayIsUnordered(opt)   (((opt) & kXMP_PropArrayIsOrdered) == 0)
-#define XMP_ArrayIsOrdered(opt)     (((opt) & kXMP_PropArrayIsOrdered) != 0)
-#define XMP_ArrayIsAlternate(opt)   (((opt) & kXMP_PropArrayIsAlternate) != 0)
-#define XMP_ArrayIsAltText(opt)     (((opt) & kXMP_PropArrayIsAltText) != 0)
-
-#define XMP_PropHasQualifiers(opt)  (((opt) & kXMP_PropHasQualifiers) != 0)
-#define XMP_PropIsQualifier(opt)    (((opt) & kXMP_PropIsQualifier) != 0)
-#define XMP_PropHasLang(opt)        (((opt) & kXMP_PropHasLang) != 0)
-
-#define XMP_NodeIsSchema(opt)       (((opt) & kXMP_SchemaNode) != 0)
-#define XMP_PropIsAlias(opt)        (((opt) & kXMP_PropIsAlias) != 0)
-
-// -------------------------------------------------------------------------------------------------
-
-/// Option bit flags for the \c TXMPMeta property accessor functions.
-enum {
-
-	/// The XML string form of the property value is a URI, use rdf:resource attribute. DISCOURAGED
-    kXMP_PropValueIsURI       = 0x00000002UL,
-
-	// ------------------------------------------------------
-    // Options relating to qualifiers attached to a property.
-
-	/// The property has qualifiers, includes \c rdf:type and \c xml:lang.
-    kXMP_PropHasQualifiers    = 0x00000010UL,
-
-	/// This is a qualifier for some other property, includes \c rdf:type and \c xml:lang.
-	/// Qualifiers can have arbitrary structure, and can themselves have qualifiers. If the
-	/// qualifier itself has a structured value, this flag is only set for the top node of the
-	/// qualifier's subtree.
-    kXMP_PropIsQualifier      = 0x00000020UL,
-
-	/// Implies \c #kXMP_PropHasQualifiers, property has \c xml:lang.
-    kXMP_PropHasLang          = 0x00000040UL,
-
-	/// Implies \c #kXMP_PropHasQualifiers, property has \c rdf:type.
-    kXMP_PropHasType          = 0x00000080UL,
-
-	// --------------------------------------------
-    // Options relating to the data structure form.
-
-	/// The value is a structure with nested fields.
-    kXMP_PropValueIsStruct    = 0x00000100UL,
-
-	/// The value is an array (RDF alt/bag/seq). The "ArrayIs..." flags identify specific types
-	/// of array; default is a general unordered array, serialized using an \c rdf:Bag container.
-    kXMP_PropValueIsArray     = 0x00000200UL,
-
-	/// The item order does not matter.
-    kXMP_PropArrayIsUnordered = kXMP_PropValueIsArray,
-
-	/// Implies \c #kXMP_PropValueIsArray, item order matters. It is serialized using an \c rdf:Seq container.
-    kXMP_PropArrayIsOrdered   = 0x00000400UL,
-
-	/// Implies \c #kXMP_PropArrayIsOrdered, items are alternates. It is serialized using an \c rdf:Alt container.
-    kXMP_PropArrayIsAlternate = 0x00000800UL,
-
-	// ------------------------------------
-    // Additional struct and array options.
-
-	/// Implies \c #kXMP_PropArrayIsAlternate, items are localized text.  Each array element is a
-	/// simple property with an \c xml:lang attribute.
-    kXMP_PropArrayIsAltText   = 0x00001000UL,
-
-    // kXMP_InsertBeforeItem  = 0x00004000UL,  ! Used by SetXyz functions.
-    // kXMP_InsertAfterItem   = 0x00008000UL,  ! Used by SetXyz functions.
-
-	// ----------------------------
-    // Other miscellaneous options.
-
-	/// This property is an alias name for another property.  This is only returned by
-	/// \c TXMPMeta::GetProperty() and then only if the property name is simple, not an path expression.
-    kXMP_PropIsAlias          = 0x00010000UL,
-
-	/// This property is the base value (actual) for a set of aliases.This is only returned by
-	/// \c TXMPMeta::GetProperty() and then only if the property name is simple, not an path expression.
-    kXMP_PropHasAliases       = 0x00020000UL,
-
-	/// The value of this property is "owned" by the application, and should not generally be editable in a UI.
-    kXMP_PropIsInternal       = 0x00040000UL,
-
-	/// The value of this property is not derived from the document content.
-    kXMP_PropIsStable         = 0x00100000UL,
-
-	/// The value of this property is derived from the document content.
-    kXMP_PropIsDerived        = 0x00200000UL,
-
-    // kXMPUtil_AllowCommas   = 0x10000000UL,  ! Used by TXMPUtils::CatenateArrayItems and ::SeparateArrayItems.
-    // kXMP_DeleteExisting    = 0x20000000UL,  ! Used by TXMPMeta::SetXyz functions to delete any pre-existing property.
-    // kXMP_SchemaNode        = 0x80000000UL,  ! Returned by iterators - #define to avoid warnings
-
-	// ------------------------------
-    // Masks that are multiple flags.
-
-	/// Property type bit-flag mask for all array types
-    kXMP_PropArrayFormMask    = kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate | kXMP_PropArrayIsAltText,
-
-	/// Property type bit-flag mask for composite types (array and struct)
-    kXMP_PropCompositeMask    = kXMP_PropValueIsStruct | kXMP_PropArrayFormMask,
-
-	/// Mask for bits that are reserved for transient use by the implementation.
-    kXMP_ImplReservedMask     = 0x70000000L
-
-};
-
-#define kXMP_SchemaNode ((XMP_OptionBits)0x80000000UL)
-
-/// Option bit flags for the \c TXMPMeta property setting functions. These option bits are shared
-/// with the accessor functions:
-///   \li \c #kXMP_PropValueIsURI
-///   \li \c #kXMP_PropValueIsStruct
-///   \li \c #kXMP_PropValueIsArray
-///   \li \c #kXMP_PropArrayIsOrdered
-///   \li \c #kXMP_PropArrayIsAlternate
-///   \li \c #kXMP_PropArrayIsAltText
-enum {
-
-    /// Option for array item location: Insert a new item before the given index.
-    kXMP_InsertBeforeItem      = 0x00004000UL,
-
-    /// Option for array item location: Insert a new item after the given index.
-    kXMP_InsertAfterItem       = 0x00008000UL,
-
-    /// Delete any pre-existing property.
-    kXMP_DeleteExisting        = 0x20000000UL,
-
-	/// Bit-flag mask for property-value option bits
-    kXMP_PropValueOptionsMask  = kXMP_PropValueIsURI,
-
-	/// Bit-flag mask for array-item location bits
-    kXMP_PropArrayLocationMask = kXMP_InsertBeforeItem | kXMP_InsertAfterItem
-
-};
-
-// -------------------------------------------------------------------------------------------------
-
-/// Option bit flags for \c TXMPMeta::ParseFromBuffer().
-enum {
-
-	/// Require a surrounding \c x:xmpmeta element.
-    kXMP_RequireXMPMeta   = 0x0001UL,
-
-	/// This is the not last input buffer for this parse stream.
-    kXMP_ParseMoreBuffers = 0x0002UL,
-
-	/// Do not reconcile alias differences, throw an exception.
-    kXMP_StrictAliasing   = 0x0004UL
-
-};
-
-/// Option bit flags for \c TXMPMeta::SerializeToBuffer().
-enum {
-
-    // *** Option to remove empty struct/array, or leaf with empty value?
-
-	/// Omit the XML packet wrapper.
-    kXMP_OmitPacketWrapper   = 0x0010UL,
-
-	/// Default is a writeable packet.
-    kXMP_ReadOnlyPacket      = 0x0020UL,
-
-	/// Use a compact form of RDF.
-    kXMP_UseCompactFormat    = 0x0040UL,
-
-	/// Include a padding allowance for a thumbnail image.
-    kXMP_IncludeThumbnailPad = 0x0100UL,
-
-	/// The padding parameter is the overall packet length.
-    kXMP_ExactPacketLength   = 0x0200UL,
-
-	/// Show aliases as XML comments.
-    kXMP_WriteAliasComments  = 0x0400UL,
-
-	/// Omit all formatting whitespace.
-    kXMP_OmitAllFormatting   = 0x0800UL,
-    
-    /// Omit the x:xmpmeta element surrounding the rdf:RDF element.
-    kXMP_OmitXMPMetaElement  = 0x1000UL,
-
-    _XMP_LittleEndian_Bit    = 0x0001UL,  // ! Don't use directly, see the combined values below!
-    _XMP_UTF16_Bit           = 0x0002UL,
-    _XMP_UTF32_Bit           = 0x0004UL,
-
-	/// Bit-flag mask for encoding-type bits
-    kXMP_EncodingMask        = 0x0007UL,
-
-	/// Use UTF8 encoding
-    kXMP_EncodeUTF8          = 0UL,
-
-	/// Use UTF16 big-endian encoding
-    kXMP_EncodeUTF16Big      = _XMP_UTF16_Bit,
-
-	/// Use UTF16 little-endian encoding
-    kXMP_EncodeUTF16Little   = _XMP_UTF16_Bit | _XMP_LittleEndian_Bit,
-
-	/// Use UTF32 big-endian encoding
-    kXMP_EncodeUTF32Big      = _XMP_UTF32_Bit,
-
-	/// Use UTF13 little-endian encoding
-    kXMP_EncodeUTF32Little   = _XMP_UTF32_Bit | _XMP_LittleEndian_Bit
-
-};
-
-// -------------------------------------------------------------------------------------------------
-
-/// Option bit flags for \c TXMPIterator construction.
-enum {
-
-	/// The low 8 bits are an enum of what data structure to iterate.
-    kXMP_IterClassMask      = 0x00FFUL,
-
-    /// Iterate the property tree of a TXMPMeta object.
-    kXMP_IterProperties     = 0x0000UL,
-
-	/// Iterate the global alias table.
-    kXMP_IterAliases        = 0x0001UL,
-
-	/// Iterate the global namespace table.
-    kXMP_IterNamespaces     = 0x0002UL,
-
-	/// Just do the immediate children of the root, default is subtree.
-    kXMP_IterJustChildren   = 0x0100UL,
-
-	/// Just do the leaf nodes, default is all nodes in the subtree.
-    kXMP_IterJustLeafNodes  = 0x0200UL,
-
-	/// Return just the leaf part of the path, default is the full path.
-    kXMP_IterJustLeafName   = 0x0400UL,
-
-	 /// Include aliases, default is just actual properties.
-    kXMP_IterIncludeAliases = 0x0800UL,
-
-	 /// Omit all qualifiers.
-    kXMP_IterOmitQualifiers = 0x1000UL
-
-};
-
-/// Option bit flags for \c TXMPIterator::Skip().
-enum {
-
-	/// Skip the subtree below the current node.
-    kXMP_IterSkipSubtree    = 0x0001UL,
-
-	/// Skip the subtree below and remaining siblings of the current node.
-    kXMP_IterSkipSiblings   = 0x0002UL
-
-};
-
-// -------------------------------------------------------------------------------------------------
-/// Option bit flags for \c TXMPUtils::CatenateArrayItems() and \c TXMPUtils::SeparateArrayItems().
-/// These option bits are shared with the accessor functions:
-///   \li \c #kXMP_PropValueIsArray,
-///   \li \c #kXMP_PropArrayIsOrdered, 
-///   \li \c #kXMP_PropArrayIsAlternate,
-///   \li \c #kXMP_PropArrayIsAltText
-enum {
-
-	/// Allow commas in item values, default is separator.
-    kXMPUtil_AllowCommas      = 0x10000000UL
-
-};
-
-/// Option bit flags for \c TXMPUtils::RemoveProperties() and \c TXMPUtils::AppendProperties().
-enum {
-
-	 /// Do all properties, default is just external properties.
-    kXMPUtil_DoAllProperties   = 0x0001UL,
-
-	/// Replace existing values, default is to leave them.
-    kXMPUtil_ReplaceOldValues  = 0x0002UL,
-
-	/// Delete properties if the new value is empty.
-    kXMPUtil_DeleteEmptyValues = 0x0004UL,
-
-	/// Include aliases, default is just actual properties.
-    kXMPUtil_IncludeAliases    = 0x0800UL
-
-};
-
-// =================================================================================================
-// Types and Constants for XMPFiles
-// ================================
-
-/// File format constants for use with XMPFiles.
-enum {
-    
-    // ! Hex used to avoid gcc warnings. Leave the constants so the text reads big endian. There
-    // ! seems to be no decent way on UNIX to determine the target endianness at compile time.
-    // ! Forcing it on the client isn't acceptable.
-
-	// --------------------
-    // Public file formats.
-
-	/// Public file format constant: 'PDF '
-    kXMP_PDFFile             = 0x50444620UL,
-	/// Public file format constant: 'PS  ', general PostScript following DSC conventions
-    kXMP_PostScriptFile      = 0x50532020UL,
-	/// Public file format constant: 'EPS ', encapsulated PostScript
-    kXMP_EPSFile             = 0x45505320UL,
-
-	/// Public file format constant: 'JPEG'
-    kXMP_JPEGFile            = 0x4A504547UL,
-	/// Public file format constant: 'JPX ', JPEG 2000, ISO 15444-1
-    kXMP_JPEG2KFile          = 0x4A505820UL,
-	/// Public file format constant: 'TIFF'
-    kXMP_TIFFFile            = 0x54494646UL,
-	/// Public file format constant: 'GIF '
-    kXMP_GIFFile             = 0x47494620UL,
-	/// Public file format constant: 'PNG '
-    kXMP_PNGFile             = 0x504E4720UL,
-
-	/// Public file format constant: 'SWF '
-    kXMP_SWFFile             = 0x53574620UL,
-	/// Public file format constant: 'FLA '
-    kXMP_FLAFile             = 0x464C4120UL,
-	/// Public file format constant: 'FLV '
-    kXMP_FLVFile             = 0x464C5620UL,
-
-	/// Public file format constant: 'MOV ', Quicktime
-    kXMP_MOVFile             = 0x4D4F5620UL,
-	/// Public file format constant: 'AVI '
-    kXMP_AVIFile             = 0x41564920UL,
-	/// Public file format constant: 'CIN ', Cineon
-    kXMP_CINFile             = 0x43494E20UL,
- 	/// Public file format constant: 'WAV '
-    kXMP_WAVFile             = 0x57415620UL,
-	/// Public file format constant: 'MP3 '
-    kXMP_MP3File             = 0x4D503320UL,
-	/// Public file format constant: 'SES ', Audition session
-    kXMP_SESFile             = 0x53455320UL,
-	/// Public file format constant: 'CEL ', Audition loop
-    kXMP_CELFile             = 0x43454C20UL,
-	/// Public file format constant: 'MPEG'
-    kXMP_MPEGFile            = 0x4D504547UL,
-	/// Public file format constant: 'MP2 '
-    kXMP_MPEG2File           = 0x4D503220UL,
-	/// Public file format constant: 'MP4 ', ISO 14494-12 and -14
-    kXMP_MPEG4File           = 0x4D503420UL,
-	/// Public file format constant: 'WMAV', Windows Media Audio and Video
-    kXMP_WMAVFile            = 0x574D4156UL,
-	/// Public file format constant:  'AIFF'
-    kXMP_AIFFFile            = 0x41494646UL,
-	/// Public file format constant:  'P2  ', a collection not really a single file
-    kXMP_P2File              = 0x50322020UL,
-	/// Public file format constant:  'XDCF', a collection not really a single file
-    kXMP_XDCAM_FAMFile       = 0x58444346UL,
-	/// Public file format constant:  'XDCS', a collection not really a single file
-    kXMP_XDCAM_SAMFile       = 0x58444353UL,
-	/// Public file format constant:  'XDCX', a collection not really a single file
-    kXMP_XDCAM_EXFile        = 0x58444358UL,
-	/// Public file format constant:  'AVHD', a collection not really a single file
-    kXMP_AVCHDFile           = 0x41564844UL,
-	/// Public file format constant:  'SHDV', a collection not really a single file
-    kXMP_SonyHDVFile         = 0x53484456UL,
-
-	/// Public file format constant: 'HTML'
-    kXMP_HTMLFile            = 0x48544D4CUL,
-	/// Public file format constant: 'XML '
-    kXMP_XMLFile             = 0x584D4C20UL,
-	/// Public file format constant:  'text'
-    kXMP_TextFile            = 0x74657874UL,
-
-	// -------------------------------
-    // Adobe application file formats.
-
-	/// Adobe application file format constant: 'PSD '
-    kXMP_PhotoshopFile       = 0x50534420UL,
-	/// Adobe application file format constant: 'AI  '
-    kXMP_IllustratorFile     = 0x41492020UL,
-	/// Adobe application file format constant: 'INDD'
-    kXMP_InDesignFile        = 0x494E4444UL,
-	/// Adobe application file format constant: 'AEP '
-    kXMP_AEProjectFile       = 0x41455020UL,
-	/// Adobe application file format constant: 'AET ', After Effects Project Template
-    kXMP_AEProjTemplateFile  = 0x41455420UL,
-	/// Adobe application file format constant: 'FFX '
-    kXMP_AEFilterPresetFile  = 0x46465820UL,
-	/// Adobe application file format constant: 'NCOR'
-    kXMP_EncoreProjectFile   = 0x4E434F52UL,
-	/// Adobe application file format constant: 'PRPJ'
-    kXMP_PremiereProjectFile = 0x5052504AUL,
-	/// Adobe application file format constant: 'PRTL'
-    kXMP_PremiereTitleFile   = 0x5052544CUL,
-	/// Adobe application file format constant: 'UCF ', Universal Container Format
-	kXMP_UCFFile             = 0x55434620UL,
-
-	// -------
-    // Others.
-
-	/// Unknown file format constant: '    '
-    kXMP_UnknownFile         = 0x20202020UL
-
-};
-
-/// Type for file format identification constants. See \c #kXMP_PDFFile and following.
-typedef XMP_Uns32 XMP_FileFormat;
-
-// -------------------------------------------------------------------------------------------------
-
-/// Byte-order masks, do not use directly
-enum {
-    kXMP_CharLittleEndianMask = 1,
-    kXMP_Char16BitMask        = 2,
-    kXMP_Char32BitMask        = 4
-};
-
-/// Constants to allow easy testing for 16/32 bit and big/little endian.
-enum {
-	/// 8-bit
-    kXMP_Char8Bit        = 0,
-	/// 16-bit big-endian
-    kXMP_Char16BitBig    = kXMP_Char16BitMask,
-	/// 16-bit little-endian
-    kXMP_Char16BitLittle = kXMP_Char16BitMask | kXMP_CharLittleEndianMask,
-	/// 32-bit big-endian
-    kXMP_Char32BitBig    = kXMP_Char32BitMask,
-	/// 32-bit little-endian
-    kXMP_Char32BitLittle = kXMP_Char32BitMask | kXMP_CharLittleEndianMask,
-	/// Variable or not-yet-known cases
-    kXMP_CharUnknown     = 1
-};
-
-/// \name Macros to test components of the character form mask
-/// @{
-///
-/// \def XMP_CharFormIs16Bit
-/// \brief Macro reports the encoding of a character.
-/// \param f The character to check.
-///
-/// \def XMP_CharFormIs32Bit
-/// \brief Macro reports the encoding of a character.
-/// \param f The character to check.
-///
-/// \def XMP_CharFormIsBigEndian
-/// \brief Macro reports the byte-order of a character.
-/// \param f The character to check.
-///
-/// \def XMP_CharFormIsLittleEndian
-/// \brief Macro reports the byte-order of a character.
-/// \param f The character to check.
-///
-/// \def XMP_GetCharSize
-/// \brief Macro reports the byte-size of a character.
-/// \param f The character to check.
-///
-/// \def XMP_CharToSerializeForm
-/// \brief Macro converts \c XMP_Uns8 to \c XMP_OptionBits.
-/// \param cf The character to convert.
-///
-/// \def XMP_CharFromSerializeForm
-/// \brief Macro converts \c XMP_OptionBits to \c XMP_Uns8.
-/// \param sf The character to convert.
-///
-/// @}
-
-#define XMP_CharFormIs16Bit(f)         ( ((int)(f) & kXMP_Char16BitMask) != 0 )
-#define XMP_CharFormIs32Bit(f)         ( ((int)(f) & kXMP_Char32BitMask) != 0 )
-#define XMP_CharFormIsBigEndian(f)     ( ((int)(f) & kXMP_CharLittleEndianMask) == 0 )
-#define XMP_CharFormIsLittleEndian(f)  ( ((int)(f) & kXMP_CharLittleEndianMask) != 0 )
-#define XMP_GetCharSize(f)             ( ((int)(f)&6) == 0 ? 1 : (int)(f)&6 )
-#define XMP_CharToSerializeForm(cf)    ( (XMP_OptionBits)(cf) )
-#define XMP_CharFromSerializeForm(sf)  ( (XMP_Uns8)(sf) )
-
-/// \def kXMPFiles_UnknownOffset
-/// \brief Constant for an unknown packet offset within a file.
-#define kXMPFiles_UnknownOffset	((XMP_Int64)-1)
-
-/// \def kXMPFiles_UnknownLength
-/// \brief Constant for an unknown packet length within a file.
-#define kXMPFiles_UnknownLength	((XMP_Int32)-1)
-
-/// XMP packet description
-struct XMP_PacketInfo {
-
-	/// Packet offset in the file in bytes, -1 if unknown.
-    XMP_Int64 offset;
-	/// Packet length in the file in bytes, -1 if unknown.
-    XMP_Int32 length;
-	/// Packet padding size in bytes, zero if unknown.
-    XMP_Int32 padSize;   // Zero if unknown.
-
-	/// Character format using the values \c kXMP_Char8Bit, \c kXMP_Char16BitBig, etc.
-    XMP_Uns8  charForm;
-	/// True if there is a packet wrapper and the trailer says writeable by dumb packet scanners.
-    XMP_Bool  writeable;
-    /// True if there is a packet wrapper, the "<?xpacket...>" XML processing instructions.
-    XMP_Bool  hasWrapper;
-
-	/// Padding to make the struct's size be a multiple 4.
-    XMP_Uns8  pad;
-
-	/// Default constructor.
-	XMP_PacketInfo() : offset(kXMPFiles_UnknownOffset), length(kXMPFiles_UnknownLength),
-					   padSize(0), charForm(0), writeable(0), hasWrapper(0), pad(0) {};
-
-};
-
-/// Version of the XMP_PacketInfo type
-enum {
-	/// Version of the XMP_PacketInfo type
-	kXMP_PacketInfoVersion = 3
-};
-
-// -------------------------------------------------------------------------------------------------
-
-/// Values for \c XMP_ThumbnailInfo::tnailFormat.
-enum {
-	/// The thumbnail data has an unknown format.
-    kXMP_UnknownTNail = 0,
-	/// The thumbnail data is a JPEG stream, presumably compressed.
-    kXMP_JPEGTNail    = 1,
-	/// The thumbnail data is a TIFF stream, presumably uncompressed.
-    kXMP_TIFFTNail    = 2,
-	/// The thumbnail data is in the format of Photoshop Image Resource 1036.
-    kXMP_PShopTNail   = 3
-};
-
-/// Thumbnail descriptor
-struct XMP_ThumbnailInfo {
-
-	/// The format of the containing file.
-    XMP_FileFormat   fileFormat;
-	/// Full image size in pixels.
-    XMP_Uns32        fullWidth, fullHeight;
-	/// Thumbnail image size in pixels.
-    XMP_Uns32        tnailWidth, tnailHeight;
-	/// Orientation of full image and thumbnail, as defined by Exif for tag 274.
-
-    XMP_Uns16        fullOrientation, tnailOrientation;
-	/// Raw image data from the host file, valid for life of the owning \c XMPFiles object. Do not modify!
-    const XMP_Uns8 * tnailImage;
-	/// The size in bytes of the thumbnail image data.
-    XMP_Uns32        tnailSize;
-	/// The format of the thumbnail image data.
-    XMP_Uns8         tnailFormat;
-
-	/// Padding to make the struct's size be a multiple 4.
-    XMP_Uns8         pad1, pad2, pad3;
-
-	/// Default constructor.
-	XMP_ThumbnailInfo() : fileFormat(kXMP_UnknownFile), fullWidth(0), fullHeight(0),
-						  tnailWidth(0), tnailHeight(0), fullOrientation(0), tnailOrientation(0),
-						  tnailImage(0), tnailSize(0), tnailFormat(kXMP_UnknownTNail) {};
-
-};
-
-/// Version of the XMP_ThumbnailInfo type
-enum {
-	/// Version of the XMP_ThumbnailInfo type
-	kXMP_ThumbnailInfoVersion = 1
-};
-
-// -------------------------------------------------------------------------------------------------
-
-/// Option bit flags for \c TXMPFiles::Initialize().
-enum {
-	/// Do not initialize QuickTime, the client will.
-    kXMPFiles_NoQuickTimeInit = 0x0001
-};
-
-/// Option bit flags for \c TXMPFiles::GetFormatInfo().
-enum {
-
-	/// Can inject first-time XMP into an existing file.
-    kXMPFiles_CanInjectXMP        = 0x00000001,
-
-	/// Can expand XMP or other metadata in an existing file.
-    kXMPFiles_CanExpand           = 0x00000002,
-
-	/// Can copy one file to another, writing new metadata.
-    kXMPFiles_CanRewrite          = 0x00000004,
-
-	 /// Can expand, but prefers in-place update.
-    kXMPFiles_PrefersInPlace      = 0x00000008,
-
-	/// Supports reconciliation between XMP and other forms.
-    kXMPFiles_CanReconcile        = 0x00000010,
-
-	 /// Allows access to just the XMP, ignoring other forms.
-    kXMPFiles_AllowsOnlyXMP       = 0x00000020,
-
-	/// File handler returns raw XMP packet information.
-    kXMPFiles_ReturnsRawPacket    = 0x00000040,
-
-	 /// File handler returns native thumbnail.
-    kXMPFiles_ReturnsTNail        = 0x00000080,
-
-	/// The file handler does the file open and close.
-    kXMPFiles_HandlerOwnsFile     = 0x00000100,
-
-	/// The file handler allows crash-safe file updates.
-    kXMPFiles_AllowsSafeUpdate    = 0x00000200,
-
-	/// The file format needs the XMP packet to be read-only.
-    kXMPFiles_NeedsReadOnlyPacket = 0x00000400,
-
-	/// The file handler uses a "sidecar" file for the XMP.
-    kXMPFiles_UsesSidecarXMP      = 0x00000800,
-
-	/// The format is folder oriented, for example the P2 video format.
-    kXMPFiles_FolderBasedFormat   = 0x00001000
-
-};
-
-/// Option bit flags for \c TXMPFiles::OpenFile().
-enum {
-
-	/// Open for read-only access.
-    kXMPFiles_OpenForRead           = 0x00000001,
-
-	/// Open for reading and writing.
-    kXMPFiles_OpenForUpdate         = 0x00000002,
-
-	/// Only the XMP is wanted, allows space/time optimizations.
-    kXMPFiles_OpenOnlyXMP           = 0x00000004,
-
-	/// Cache thumbnail if possible, \c TXMPFiles::GetThumbnail() will be called.
-    kXMPFiles_OpenCacheTNail        = 0x00000008,
-
-	/// Be strict about locating XMP and reconciling with other forms.
-    kXMPFiles_OpenStrictly          = 0x00000010,
-
-	/// Require the use of a smart handler.
-    kXMPFiles_OpenUseSmartHandler   = 0x00000020,
-
-	/// Force packet scanning, do not use a smart handler.
-    kXMPFiles_OpenUsePacketScanning = 0x00000040,
-
-	/// Only packet scan files "known" to need scanning.
-    kXMPFiles_OpenLimitedScanning   = 0x00000080,
-    
-    /// Attempt to repair a file opened for update, default is to not open (throw an exception).
-    kXMPFiles_OpenRepairFile        = 0x00000100,
-
-	 /// Set if calling from background thread.
-    kXMPFiles_OpenInBackground      = 0x10000000
-
-};
-
-// A note about kXMPFiles_OpenInBackground. The XMPFiles handler for .mov files currently uses
-// QuickTime. On Macintosh, calls to Enter/ExitMovies versus Enter/ExitMoviesOnThread must be made.
-// This option is used to signal background use so that the .mov handler can behave appropriately.
-
-/// Option bit flags for \c TXMPFiles::CloseFile().
-enum {
-	/// Write into a temporary file and swap for crash safety.
-    kXMPFiles_UpdateSafely = 0x0001
-};
-
-// =================================================================================================
-// Exception codes
-// ===============
-
-/// \name Errors Exception handling
-/// @{
-///
-/// XMP Tookit errors result in throwing an \c XMP_Error exception. Any exception thrown within the
-/// XMP Toolkit is caught in the toolkit and rethrown as an \c XMP_Error.
-///
-/// The \c XMP_Error class contains a numeric code and an English explanation. New numeric codes may
-/// be added at any time. There are typically many possible explanations for each numeric code. The
-/// explanations try to be precise about the specific circumstances causing the error.
-///
-/// \note The explanation string is for debugging use only. It must not be shown to users in a
-/// final product. It is written for developers not users, and never localized.
-///
-
-/// XMP Toolkit error, associates an error code with a descriptive error string.
-class XMP_Error {
-public:
-
-	/// @brief Constructor for an XMP_Error.
-	///
-	/// @param _id The numeric code.
-	///
-	/// @param _errMsg The descriptive string, for debugging use only. It must not be shown to users
-	/// in a final product. It is written for developers, not users, and never localized.
-	XMP_Error ( XMP_Int32 _id, XMP_StringPtr _errMsg ) : id(_id), errMsg(_errMsg) {};
-
-	/// Retrieves the numeric code from an XMP_Error.
-	inline XMP_Int32     GetID() const     { return id; };
-
-	/// Retrieves the descriptive string from an XMP_Error.
-	inline XMP_StringPtr GetErrMsg() const { return errMsg; };
-
-private:
-	/// Exception code. See constants \c #kXMPErr_Unknown and following.
-	XMP_Int32     id;
-	/// Descriptive string, for debugging use only. It must not be shown to users in a final
-	/// product. It is written for developers, not users, and never localized.
-	XMP_StringPtr errMsg;
-};
-
-/// Exception code constants
-enum {
-
-	// --------------------
-    // Generic error codes.
-   
-	/// Generic unknown error
-    kXMPErr_Unknown          =   0,
-	/// Generic undefined error
-    kXMPErr_TBD              =   1,
-	/// Generic unavailable error
-    kXMPErr_Unavailable      =   2,
-	/// Generic bad object error
-    kXMPErr_BadObject        =   3,
-	/// Generic bad parameter error
-    kXMPErr_BadParam         =   4,
-	/// Generic bad value error
-    kXMPErr_BadValue         =   5,
-	/// Generic assertion failure
-    kXMPErr_AssertFailure    =   6,
-	/// Generic enforcement failure
-    kXMPErr_EnforceFailure   =   7,
-	/// Generic unimplemented error
-    kXMPErr_Unimplemented    =   8,
-	/// Generic internal failure
-    kXMPErr_InternalFailure  =   9,
-	/// Generic deprecated error
-    kXMPErr_Deprecated       =  10,
-	/// Generic external failure
-    kXMPErr_ExternalFailure  =  11,
-	/// Generic user abort error
-    kXMPErr_UserAbort        =  12,
-	/// Generic standard exception
-    kXMPErr_StdException     =  13,
-	/// Generic unknown exception
-    kXMPErr_UnknownException =  14,
-	/// Generic out-of-memory error
-    kXMPErr_NoMemory         =  15,
-
-	// ------------------------------------
-    // More specific parameter error codes.
-
-	/// Bad schema parameter
-    kXMPErr_BadSchema        = 101,
-	/// Bad XPath parameter
-    kXMPErr_BadXPath         = 102,
-	/// Bad options parameter
-    kXMPErr_BadOptions       = 103,
-	/// Bad index parameter
-    kXMPErr_BadIndex         = 104,
-	/// Bad iteration position
-    kXMPErr_BadIterPosition  = 105,
-	/// XML parsing error
-    kXMPErr_BadParse         = 106,
-	/// Serialization error
-    kXMPErr_BadSerialize     = 107,
-	/// File format error
-    kXMPErr_BadFileFormat    = 108,
-	/// No file handler found for format
-    kXMPErr_NoFileHandler    = 109,
-	/// Data too large for JPEG file format
-    kXMPErr_TooLargeForJPEG  = 110,
-
-	// -----------------------------------------------
-    // File format and internal structure error codes.
-
-	/// XML format error
-    kXMPErr_BadXML           = 201,
-	/// RDF format error
-    kXMPErr_BadRDF           = 202,
-	/// XMP format error
-    kXMPErr_BadXMP           = 203,
-	/// Empty iterator
-    kXMPErr_EmptyIterator    = 204,
-	/// Unicode error
-    kXMPErr_BadUnicode       = 205,
-	/// TIFF format error
-    kXMPErr_BadTIFF          = 206,
-	/// JPEG format error
-    kXMPErr_BadJPEG          = 207,
-	/// PSD format error
-    kXMPErr_BadPSD           = 208,
-	/// PSIR format error
-    kXMPErr_BadPSIR          = 209,
-	/// IPTC format error
-    kXMPErr_BadIPTC          = 210,
-	/// MPEG format error
-    kXMPErr_BadMPEG          = 211
-
-};
-
-/// @}
-
-// =================================================================================================
-// Client callbacks
-// ================
-
-// -------------------------------------------------------------------------------------------------
-/// \name Special purpose callback functions
-/// @{
-
-/// A signed 32-bit integer used as a status result for the output callback routine,
-/// \c XMP_TextOutputProc. Zero means no error, all other values except -1 are private to the callback.
-/// The callback is wrapped to prevent exceptions being thrown across DLL boundaries. Any exceptions
-/// thrown out of the callback cause a return status of -1.
-
-typedef XMP_Int32 XMP_Status;
-
-// -------------------------------------------------------------------------------------------------
-/// The signature of a client-defined callback for text output from XMP Toolkit debugging
-/// operations. The callback is invoked one or more times for each line of output. The end of a line
-/// is signaled by a '\\n' character at the end of the buffer. Formatting newlines are never present
-/// in the middle of a buffer, but values of properties might contain any UTF-8 characters.
-///
-/// @param refCon A pointer to client-defined data passed to the TextOutputProc.
-///
-/// @param buffer  A string containing one line of output.
-///
-/// @param bufferSize The number of characters in the output buffer.
-///
-/// @return A success/fail status value. Any failure result aborts the output.
-///
-/// @see \c TXMPMeta::DumpObject()
-
-typedef XMP_Status (* XMP_TextOutputProc) ( void *        refCon,
-                                            XMP_StringPtr buffer,
-                                            XMP_StringLen bufferSize );
-
-// -------------------------------------------------------------------------------------------------
-/// The signature of a client-defined callback to check for a user request to abort a time-consuming
-/// operation within XMPFiles.
-///
-/// @param arg A pointer to caller-defined data passed from the registration call.
-///
-/// @return True to abort the current operation, which results in an exception being thrown.
-///
-/// @see \c TXMPFiles::SetAbortProc()
-
-typedef bool (* XMP_AbortProc) ( void * arg );	// Used by .
-
-/// @}
-
-// =================================================================================================
-// Stuff with no better place to be
-// ================================
-
-/// XMP Toolkit version information
-typedef struct XMP_VersionInfo {
-	/// The primary release number, the "1" in version "1.2.3".
-    XMP_Uns8      major;
-	/// The secondary release number, the "2" in version "1.2.3".
-    XMP_Uns8      minor;
-	/// The tertiary release number, the "3" in version "1.2.3".
-    XMP_Uns8      micro;
-	 /// A 0/1 boolean value, true if this is a debug build.
-    XMP_Bool      isDebug;
-	 /// A rolling build number, monotonically increasing in a release.
-    XMP_Uns32     build;
-	 /// Individual feature implementation flags.
-    XMP_Uns32     flags;
-	 /// A comprehensive version information string.
-    XMP_StringPtr message;
-} XMP_VersionInfo;
-
-// =================================================================================================
-
-#if __cplusplus
-} // extern "C"
-#endif
-
-#endif  // __XMP_Const_h__
diff --git a/xmpsdk/include/XMP_Environment.h b/xmpsdk/include/XMP_Environment.h
deleted file mode 100644
index bfaa5a83..00000000
--- a/xmpsdk/include/XMP_Environment.h
+++ /dev/null
@@ -1,164 +0,0 @@
-#ifndef __XMP_Environment_h__
-#define __XMP_Environment_h__ 1
-
-// =================================================================================================
-// XMP_Environment.h - Build environment flags for the XMP toolkit.
-// ================================================================
-//
-// This header is just C preprocessor macro definitions to set up the XMP toolkit build environment.
-// It must be the first #include in any chain since it might affect things in other #includes.
-//
-// =================================================================================================
-
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-// =================================================================================================
-// Determine the Platform
-// ======================
-
-// One of MAC_ENV, WIN_ENV, or UNIX_ENV must be defined by the client. Since some other code
-// requires these to be defined without values, they are only used here to define XMP-specific
-// macros with 0 or 1 values.
-
-/* 20-Oct-07, ahu: Determine the platform, set the above defines accordingly.                     */
-
-#if !defined(_FILE_OFFSET_BITS)
-#define _FILE_OFFSET_BITS 64
-#endif
-
-#if defined __CYGWIN32__ && !defined __CYGWIN__
-   /* For backwards compatibility with Cygwin b19 and
-      earlier, we define __CYGWIN__ here, so that
-      we can rely on checking just for that macro. */
-# define __CYGWIN__  __CYGWIN32__
-#endif
-#if defined WIN32 && !defined __CYGWIN__
-# define WIN_ENV 1
-/* Todo: How to correctly recognize a Mac platform? */
-#elif defined macintosh || defined MACOS_CLASSIC || defined MACOS_X_UNIX || defined MACOS_X || defined MACOS
-# define MAC_ENV 1
-#else 
-# define UNIX_ENV 1
-#endif
-
-// ! Tempting though it might be to have a standard macro for big or little endian, there seems to
-// ! be no decent way to do that on our own in UNIX. Forcing it on the client isn't acceptable.
-
-#if defined ( MAC_ENV )
-
-	#if 0	// ! maybe someday - ! MAC_ENV
-		#error "MAC_ENV must be defined so that \"#if MAC_ENV\" is true"
-	#endif
-	
-    #if defined ( WIN_ENV ) || defined ( UNIX_ENV )
-        #error "XMP environment error - must define only one of MAC_ENV, WIN_ENV, or UNIX_ENV"
-    #endif
-
-    #define XMP_MacBuild  1
-    #define XMP_WinBuild  0
-    #define XMP_UNIXBuild 0
-
-#elif defined ( WIN_ENV )
-
-	#if 0	// ! maybe someday - ! WIN_ENV
-		#error "WIN_ENV must be defined so that \"#if WIN_ENV\" is true"
-	#endif
-	
-    #if defined ( UNIX_ENV )
-        #error "XMP environment error - must define only one of MAC_ENV, WIN_ENV, or UNIX_ENV"
-    #endif
-
-    #define XMP_MacBuild  0
-    #define XMP_WinBuild  1
-    #define XMP_UNIXBuild 0
-
-#elif defined ( UNIX_ENV )
-
-	#if 0	// ! maybe someday - ! UNIX_ENV
-		#error "UNIX_ENV must be defined so that \"#if UNIX_ENV\" is true"
-	#endif
-	
-    #define XMP_MacBuild  0
-    #define XMP_WinBuild  0
-    #define XMP_UNIXBuild 1
-
-#else
-
-    #error "XMP environment error - must define one of MAC_ENV, WIN_ENV, or UNIX_ENV"
-
-#endif
-
-// =================================================================================================
-// Common Macros
-// =============
-
-#if defined ( DEBUG )
-    #if defined ( NDEBUG )
-		#undef NDEBUG
-		#warning
-		#warning "XMP environment - DEBUG and NDEBUG defined.  NDEBUG has been undefined"
-		#warning
-    #endif
-    #define XMP_DebugBuild 1
-#endif
-
-#if defined ( NDEBUG )
-    #define XMP_DebugBuild 0
-#endif
-
-#ifndef XMP_DebugBuild
-    #define XMP_DebugBuild 0
-#endif
-
-#if XMP_DebugBuild
-    #include <stdio.h>  // The assert macro needs printf.
-#endif
-
-#ifndef XMP_64
-	#if _WIN64
-		#define XMP_64 1
-	#else
-		#define XMP_64 0
-	#endif
-#endif
-
-#define UNUSED(x) (void)(x)
-
-// =================================================================================================
-// Macintosh Specific Settings
-// ===========================
-
-// =================================================================================================
-// Windows Specific Settings
-// =========================
-
-// =================================================================================================
-// UNIX Specific Settings
-// ======================
-
-// =================================================================================================
-
-#endif  // __XMP_Environment_h__
-
-/*
-  If you're using Solaris and the Solaris Studio compiler, then you really
-  do need to use -library=stdcxx4 along with these inclusions below
-*/
-#if defined(OS_SOLARIS)
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include <stdlib.h>
-#include <math.h>
-#if defined(__cplusplus)
-#include <ios>
-#include <fstream>
-#endif
-#endif
-
diff --git a/xmpsdk/include/XMP_Version.h b/xmpsdk/include/XMP_Version.h
deleted file mode 100644
index f8b0ea81..00000000
--- a/xmpsdk/include/XMP_Version.h
+++ /dev/null
@@ -1,45 +0,0 @@
-#ifndef __XMP_Version_h__
-#define __XMP_Version_h__ 1
-
-/* --------------------------------------------------------------------------------------------- */
-/* ** IMPORTANT ** This file must be usable by strict ANSI C compilers. No "//" comments, etc.   */
-/* --------------------------------------------------------------------------------------------- */
-
-/*
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-*/
-
-/* ============================================================================================= */
-/**
-XMP Toolkit Version Information
-
-Version information for the XMP toolkit is stored in the executable and available through a runtime
-call, <tt>SXMPMeta::GetVersionInfo</tt>. In addition a static version number is defined in this
-header. The information in the executable or returned by <tt>SXMPMeta::GetVersionInfo</tt> is about
-the implementation internals, it is runtime version information. The values defined in this header
-describe the version of the API used at client compile time. They do not necessarily relate to the
-runtime version.
-
-Important: Do not display the static values defined here to users as the version of XMP in use. Do
-not base runtime decisions on just this static version. It is OK to compare the static and runtime
-versions.
-
-*/
-/* ============================================================================================= */
-
-#define XMP_API_VERSION_MAJOR  4
-#define XMP_API_VERSION_MINOR  4
-#define XMP_API_VERSION_MICRO  0
-
-#define XMP_API_VERSION 4.4
-#define XMP_API_VERSION_STRING "4.4.0-Exiv2"
-
-/* ============================================================================================= */
-
-#endif /* __XMP_Version_h__ */
diff --git a/xmpsdk/include/client-glue/TXMPIterator.incl_cpp b/xmpsdk/include/client-glue/TXMPIterator.incl_cpp
deleted file mode 100644
index 672203e2..00000000
--- a/xmpsdk/include/client-glue/TXMPIterator.incl_cpp
+++ /dev/null
@@ -1,226 +0,0 @@
-// =================================================================================================
-// ADOBE SYSTEMS INCORPORATED
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved
-//
-// NOTICE:	Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-//	================================================================================================
-/// \file TXMPIterator.incl_cpp
-/// \brief The implementation of the TXMPIterator template class.
-
-#include "XMPSDK.hpp"
-#include "client-glue/WXMP_Common.hpp"
-#include "client-glue/WXMPIterator.hpp"
-
-// =================================================================================================
-// Implementation Guidelines
-// =========================
-//
-// The implementations of the template functions are very stylized. The jobs done in this code are:
-//
-//	1. Set up the xmpIter template data member in the constructors.
-//	2. Call through to the appropriate WXMPIterator function.
-//	3. Copy returned strings and release the threading lock.
-//
-// The various kinds of functions follow similar patterns, first assuming no returned string:
-//
-// Constructors - Use an initializer for the xmpIter data member to call the WXMPIterator constructor.
-// Destructor - Let the WXMPIterator destructor be implicitly called for the xmpIter data member.
-// Static function - Simply call the corresponding WXMPIterator static function.
-// Non-static function - Simply call the corresponding WXMPIterator function using xmpIter.
-//
-// If a member function has returned strings the code looks roughly like this:
-//
-//	<<<callthrough>>>
-//	<<<checkfailure>>>
-//	if ( <<<appropriate>>> ) {
-//		if ( outStr != 0 ) outStr->assign ( outPtr, outLen );
-//		<<<unlock>>>
-//	}
-//	return result;
-//
-// The <<<callthrough>>> is the call to the wrapper, and <<<checkfailure>>> is the check and throw
-// if the wrapper reports failure. The <<<appropriate>>> check is used to determine if the string
-// should actually be assigned. For example, GetProperty can't assign the value if the property
-// does not exist. There is no <<<appropriate>>> check if it isn't, well, appropriate. Outputs are
-// always passed as explicit pointers, and null can be passed if the string is not wanted. The
-// inner implementation holds the threading lock if an output string is returned, regardless of
-// whether the client wants it or not (which the implementation does not know).
-//
-// =================================================================================================
-
-#ifndef XMP_TraceCTorDTor
-	#define XMP_TraceCTorDTor 0
-#endif
-
-#if XMP_TraceCTorDTor
-	class XIPeek {	// Hack to peek at the client ref count in the internal object.
-	public:
-		XIPeek();
-		virtual ~XIPeek();
-		XMP_Int32 clientRefs;
-	};
-#endif
-
-// -------------------------------------------------------------------------------------------------
-
-#define PropIterCTor(xmpRef,schemaNS,propName,options)												\
-	WrapCheckIterRef ( newRef, zXMPIterator_PropCTor_1 ( xmpRef, schemaNS, propName, options ) );	\
-	this->iterRef = newRef
-
-// -------------------------------------------------------------------------------------------------
-
-#define TableIterCTor(schemaNS,propName,options)													\
-	WrapCheckIterRef ( newRef, zXMPIterator_TableCTor_1 ( schemaNS, propName, options ) );	\
-	this->iterRef = newRef
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPIterator)::
-TXMPIterator ( const TXMPIterator<tStringObj> & original ) : iterRef(original.iterRef)
-{
-	WXMPIterator_IncrementRefCount_1 ( this->iterRef );
-	#if XMP_TraceCTorDTor
-		XIPeek* xiPtr = (XIPeek*)this->iterRef;
-		printf ( "Copy construct TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPIterator,void)::
-operator= ( const TXMPIterator<tStringObj> & rhs )
-{
-	#if XMP_TraceCTorDTor
-		XIPeek* xiLHS = (XIPeek*)this->iterRef;
-		XIPeek* xiRHS = (XIPeek*)rhs.iterRef;
-		printf ( "Assign TXMPIterator, lhs @ %.8X, rhs @ %.8X\n", this, &rhs );
-		printf ( "   original lhs ref = %.8X, count = %d\n", xiLHS, xiLHS->clientRefs );
-		printf ( "   original rhs ref = %.8X, count = %d\n", xiRHS, xiRHS->clientRefs );
-	#endif
-	XMPIteratorRef oldRef = this->iterRef;	// ! Decrement last so errors leave client object OK.
-	this->iterRef = rhs.iterRef;
-	WXMPIterator_IncrementRefCount_1 ( this->iterRef );
-	WXMPIterator_DecrementRefCount_1 ( oldRef );
-	#if XMP_TraceCTorDTor
-		printf ( "   result   lhs ref = %.8X, count = %d\n", xiLHS, xiLHS->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPIterator)::
-TXMPIterator() : iterRef(0)
-{
-	throw XMP_Error ( kXMPErr_Unavailable, "No default construction for XMP iterators" );
-	#if XMP_TraceCTorDTor
-		XIPeek* xiPtr = (XIPeek*)this->iterRef;
-		printf ( "Default construct TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPIterator)::
-TXMPIterator ( const TXMPMeta<tStringObj> & xmpObj,
-			   XMP_StringPtr  schemaNS,
-			   XMP_StringPtr  propName,
-			   XMP_OptionBits options /* = 0 */ ) : iterRef(0)
-{
-	PropIterCTor ( xmpObj.GetInternalRef(), schemaNS, propName, options );
-	#if XMP_TraceCTorDTor
-		XIPeek* xiPtr = (XIPeek*)this->iterRef;
-		printf ( "Construct property TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPIterator)::
-TXMPIterator ( const TXMPMeta<tStringObj> & xmpObj,
-			   XMP_StringPtr  schemaNS,
-			   XMP_OptionBits options /* = 0 */ ) : iterRef(0)
-{
-	PropIterCTor ( xmpObj.GetInternalRef(), schemaNS, "", options );
-	#if XMP_TraceCTorDTor
-		XIPeek* xiPtr = (XIPeek*)this->iterRef;
-		printf ( "Construct schema TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPIterator)::
-TXMPIterator ( const TXMPMeta<tStringObj> & xmpObj,
-			   XMP_OptionBits options /* = 0 */ ) : iterRef(0)
-{
-	PropIterCTor ( xmpObj.GetInternalRef(), "", "", options );
-	#if XMP_TraceCTorDTor
-		XIPeek* xiPtr = (XIPeek*)this->iterRef;
-		printf ( "Construct tree TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPIterator)::
-TXMPIterator ( XMP_StringPtr  schemaNS,
-			   XMP_StringPtr  propName,
-			   XMP_OptionBits options ) : iterRef(0)
-{
-	TableIterCTor ( schemaNS, propName, options );
-	#if XMP_TraceCTorDTor
-		XIPeek* xiPtr = (XIPeek*)this->iterRef;
-		printf ( "Construct table TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPIterator)::
-~TXMPIterator () throw()
-{
-	#if XMP_TraceCTorDTor
-		XIPeek* xiPtr = (XIPeek*)this->iterRef;
-		printf ( "Destruct TXMPIterator @ %.8X, ref = %.8X, count = %d\n", this, xiPtr, xiPtr->clientRefs );
-	#endif
-	WXMPIterator_DecrementRefCount_1 ( this->iterRef );
-	this->iterRef = 0;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPIterator,bool)::
-Next ( tStringObj *		schemaNS /* = 0 */,
-	   tStringObj *		propPath /* = 0 */,
-	   tStringObj *		propValue /* = 0 */,
-	   XMP_OptionBits * options /* = 0 */ )
-{
-	XMP_StringPtr schemaPtr = 0;
-	XMP_StringLen schemaLen = 0;
-	XMP_StringPtr pathPtr = 0;
-	XMP_StringLen pathLen = 0;
-	XMP_StringPtr valuePtr = 0;
-	XMP_StringLen valueLen = 0;
-	WrapCheckBool ( found, zXMPIterator_Next_1 ( &schemaPtr, &schemaLen, &pathPtr, &pathLen, &valuePtr, &valueLen, options ) );
-	if ( found ) {
-		if ( schemaNS != 0 ) schemaNS->assign ( schemaPtr, schemaLen );
-		if ( propPath != 0 ) propPath->assign ( pathPtr, pathLen );
-		if ( propValue != 0 ) propValue->assign ( valuePtr, valueLen );
-		WXMPUtils_UnlockIter_1 ( this->iterRef, 0 );
-	}
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPIterator,void)::
-Skip ( XMP_OptionBits options )
-{
-	WrapCheckVoid ( zXMPIterator_Skip_1 ( options ) );
-}
-
-// =================================================================================================
diff --git a/xmpsdk/include/client-glue/TXMPMeta.incl_cpp b/xmpsdk/include/client-glue/TXMPMeta.incl_cpp
deleted file mode 100644
index 0131aa50..00000000
--- a/xmpsdk/include/client-glue/TXMPMeta.incl_cpp
+++ /dev/null
@@ -1,935 +0,0 @@
-// =================================================================================================
-// ADOBE SYSTEMS INCORPORATED
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved
-//
-// NOTICE:	Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-//	================================================================================================
-/// \file TXMPMeta.incl_cpp
-/// \brief The implementation of the TXMPMeta template class.
-
-#include "XMPSDK.hpp"
-#include "client-glue/WXMP_Common.hpp"
-#include "client-glue/WXMPMeta.hpp"
-
-// =================================================================================================
-// Implementation Guidelines
-// =========================
-//
-// The implementations of the template functions are very stylized. ...
-//
-// =================================================================================================
-	
-#ifndef XMP_TraceCTorDTor
-	#define XMP_TraceCTorDTor 0
-#endif
-
-#if XMP_TraceCTorDTor
-	class XMPeek {	// Hack to peek at the client ref count in the internal object.
-	public:
-		XMPeek();
-		virtual ~XMPeek();
-		XMP_Int32 clientRefs;
-	};
-#endif
-
-// =================================================================================================
-// Local utilities
-// ===============
-
-// -------------------------------------------------------------------------------------------------
-
-class TOPW_Info {
-public:
-	XMP_TextOutputProc clientProc;
-	void *			   clientRefCon;
-	TOPW_Info ( XMP_TextOutputProc proc, void * refCon ) : clientProc(proc), clientRefCon(refCon) {};
-private:
-	TOPW_Info() {}; // ! Hide default constructor.
-};
-
-static XMP_Status TextOutputProcWrapper ( void *        refCon,
-                                          XMP_StringPtr buffer,
-                                          XMP_StringLen bufferSize )
-{
-	try {	// Don't let client callback exceptions propagate across DLL boundaries.
-		TOPW_Info * info = (TOPW_Info*)refCon;
-		return info->clientProc ( info->clientRefCon, buffer, bufferSize );
-	} catch ( ... ) {
-		return -1;
-	}
-}
-
-// =================================================================================================
-// Initialization and termination
-// ==============================
-
-XMP_MethodIntro(TXMPMeta,void)::
-GetVersionInfo ( XMP_VersionInfo * info )
-{
-	WrapNoCheckVoid ( zXMPMeta_GetVersionInfo_1 ( info ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-Initialize()
-{
-	WrapCheckBool ( ok, zXMPMeta_Initialize_1() );
-	return ok;
-}
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-Terminate()
-{
-	WrapNoCheckVoid ( zXMPMeta_Terminate_1() );
-}
-
-// =================================================================================================
-// Constuctors, destructor, operators
-// ==================================
-
-static XMPMetaRef DefaultCTor()
-{
-	WrapCheckMetaRef ( newRef, zXMPMeta_CTor_1() );
-	return newRef;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPMeta)::
-TXMPMeta() : xmpRef(DefaultCTor())
-{
-	#if XMP_TraceCTorDTor
-		XMPeek* xmPtr = (XMPeek*)this->xmpRef;
-		printf ( "Default construct TXMPMeta @ %.8X, ref = %.8X, count = %d\n", this, xmPtr, xmPtr->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPMeta)::
-TXMPMeta ( const TXMPMeta<tStringObj> & original ) : xmpRef(original.xmpRef)
-{
-	WXMPMeta_IncrementRefCount_1 ( this->xmpRef );
-	#if XMP_TraceCTorDTor
-		XMPeek* xmPtr = (XMPeek*)this->xmpRef;
-		printf ( "Copy construct TXMPMeta @ %.8X, ref = %.8X, count = %d\n", this, xmPtr, xmPtr->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-operator= ( const TXMPMeta<tStringObj> & rhs )
-{
-	#if XMP_TraceCTorDTor
-		XMPeek* xmLHS = (XMPeek*)this->xmpRef;
-		XMPeek* xmRHS = (XMPeek*)rhs.xmpRef;
-		printf ( "Assign TXMPMeta, lhs @ %.8X, rhs @ %.8X\n", this, &rhs );
-		printf ( "   original lhs ref = %.8X, count = %d\n", xmLHS, xmLHS->clientRefs );
-		printf ( "   original rhs ref = %.8X, count = %d\n", xmRHS, xmRHS->clientRefs );
-	#endif
-	XMPMetaRef oldRef = this->xmpRef;	// ! Decrement last so errors leave client object OK.
-	this->xmpRef = rhs.xmpRef;
-	WXMPMeta_IncrementRefCount_1 ( this->xmpRef );	// Increment the count on the new ref.
-	WXMPMeta_DecrementRefCount_1 ( oldRef );		// Decrement the count on the old ref.
-	#if XMP_TraceCTorDTor
-		printf ( "   result   lhs ref = %.8X, count = %d\n", xmLHS, xmLHS->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPMeta)::
-TXMPMeta ( XMPMetaRef _xmpRef ) : xmpRef(_xmpRef)
-{
-	WXMPMeta_IncrementRefCount_1 ( this->xmpRef );
-	#if XMP_TraceCTorDTor
-		XMPeek* xmPtr = (XMPeek*)this->xmpRef;
-		printf ( "Ref construct TXMPMeta @ %.8X, ref = %.8X, count = %d\n", this, xmPtr, xmPtr->clientRefs );
-	#endif
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPMeta)::
-TXMPMeta ( XMP_StringPtr buffer,
-           XMP_StringLen xmpSize ) : xmpRef(DefaultCTor())
-{
-	#if XMP_TraceCTorDTor
-		XMPeek* xmPtr = (XMPeek*)this->xmpRef;
-		printf ( "Parse construct TXMPMeta @ %.8X, ref = %.8X, count = %d\n", this, xmPtr, xmPtr->clientRefs );
-	#endif
-	try {
-		this->ParseFromBuffer ( buffer, xmpSize );
-	} catch ( ... ) {
-		WXMPMeta_DecrementRefCount_1 ( this->xmpRef );
-		this->xmpRef = 0;
-		throw;
-	}
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_CTorDTorIntro(TXMPMeta)::
-~TXMPMeta() throw()
-{
-	#if XMP_TraceCTorDTor
-		XMPeek* xmPtr = (XMPeek*)this->xmpRef;
-		printf ( "Destruct TXMPMeta @ %.8X, ref = %.8X, count = %d\n", this, xmPtr, xmPtr->clientRefs );
-	#endif
-	WXMPMeta_DecrementRefCount_1 ( this->xmpRef );
-	this->xmpRef = 0;
-
-}	// ~TXMPMeta ()
-
-// =================================================================================================
-// Global state functions
-// ======================
-
-XMP_MethodIntro(TXMPMeta,XMP_OptionBits)::
-GetGlobalOptions()
-{
-	WrapCheckOptions ( options, zXMPMeta_GetGlobalOptions_1() );
-	return options;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetGlobalOptions ( XMP_OptionBits options )
-{
-	WrapCheckVoid ( zXMPMeta_SetGlobalOptions_1 ( options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,XMP_Status)::
-DumpNamespaces ( XMP_TextOutputProc outProc,
-                 void *             refCon )
-{
-	TOPW_Info info ( outProc, refCon );
-	WrapCheckStatus ( status, zXMPMeta_DumpNamespaces_1 ( TextOutputProcWrapper, &info ) );
-	return status;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,XMP_Status)::
-DumpAliases ( XMP_TextOutputProc outProc,
-              void *             refCon )
-{
-	TOPW_Info info ( outProc, refCon );
-	WrapCheckStatus ( status, zXMPMeta_DumpAliases_1 ( TextOutputProcWrapper, &info ) );
-	return status;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-RegisterNamespace ( XMP_StringPtr namespaceURI,
-                    XMP_StringPtr prefix )
-{
-	WrapCheckVoid ( zXMPMeta_RegisterNamespace_1 ( namespaceURI, prefix ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetNamespacePrefix ( XMP_StringPtr namespaceURI,
-                     tStringObj *  namespacePrefix )
-{
-	XMP_StringPtr resultPtr = 0;
-	XMP_StringLen resultLen = 0;
-	WrapCheckBool ( found, zXMPMeta_GetNamespacePrefix_1 ( namespaceURI, &resultPtr, &resultLen ) );
-	if ( found ) {
-		if ( namespacePrefix != 0 ) namespacePrefix->assign ( resultPtr, resultLen );
-		WXMPMeta_Unlock_1 ( 0 );
-	}
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetNamespaceURI ( XMP_StringPtr namespacePrefix,
-                  tStringObj *  namespaceURI )
-{
-	XMP_StringPtr resultPtr = 0;
-	XMP_StringLen resultLen = 0;
-	WrapCheckBool ( found, zXMPMeta_GetNamespaceURI_1 ( namespacePrefix, &resultPtr, &resultLen ) );
-	if ( found ) {
-		if ( namespaceURI != 0 ) namespaceURI->assign ( resultPtr, resultLen );
-		WXMPMeta_Unlock_1 ( 0 );
-	}
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-DeleteNamespace ( XMP_StringPtr namespaceURI )
-{
-	WrapCheckVoid ( zXMPMeta_DeleteNamespace_1 ( namespaceURI ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-RegisterAlias ( XMP_StringPtr  aliasNS,
-                XMP_StringPtr  aliasProp,
-				XMP_StringPtr  actualNS,
-				XMP_StringPtr  actualProp,
-				XMP_OptionBits arrayForm )
-{
-	WrapCheckVoid ( zXMPMeta_RegisterAlias_1 ( aliasNS, aliasProp, actualNS, actualProp, arrayForm ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-ResolveAlias ( XMP_StringPtr    aliasNS,
-               XMP_StringPtr    aliasProp,
-			   tStringObj *     actualNS,
-			   tStringObj *     actualProp,
-			   XMP_OptionBits * arrayForm )
-{
-	XMP_StringPtr nsPtr = 0;
-	XMP_StringLen nsLen = 0;
-	XMP_StringPtr propPtr = 0;
-	XMP_StringLen propLen = 0;
-	WrapCheckBool ( found, zXMPMeta_ResolveAlias_1 ( aliasNS, aliasProp, &nsPtr, &nsLen, &propPtr, &propLen, arrayForm ) );
-	if ( found ) {
-		if ( actualNS != 0 ) actualNS->assign ( nsPtr, nsLen );
-		if ( actualProp != 0 ) actualProp->assign ( propPtr, propLen );
-		WXMPMeta_Unlock_1 ( 0 );
-	}
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-DeleteAlias ( XMP_StringPtr aliasNS,
-              XMP_StringPtr aliasProp )
-{
-	WrapCheckVoid ( zXMPMeta_DeleteAlias_1 ( aliasNS, aliasProp ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-RegisterStandardAliases ( XMP_StringPtr schemaNS )
-{
-	WrapCheckVoid ( zXMPMeta_RegisterStandardAliases_1 ( schemaNS ) );
-}
-
-// =================================================================================================
-// Basic property manipulation functions
-// =====================================
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetProperty ( XMP_StringPtr    schemaNS,
-              XMP_StringPtr    propName,
-			  tStringObj *     propValue,
-			  XMP_OptionBits * options ) const
-{
-	XMP_StringPtr resultPtr = 0;
-	XMP_StringLen resultLen = 0;
-	WrapCheckBool ( found, zXMPMeta_GetProperty_1 ( schemaNS, propName, &resultPtr, &resultLen, options ) );
-	if ( found ) {
-		if ( propValue != 0 ) propValue->assign ( resultPtr, resultLen );
-		WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 );
-	}
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetArrayItem ( XMP_StringPtr    schemaNS,
-               XMP_StringPtr    arrayName,
-               XMP_Index        itemIndex,
-			   tStringObj *     itemValue,
-			   XMP_OptionBits * options ) const
-{
-	XMP_StringPtr resultPtr = 0;
-	XMP_StringLen resultLen = 0;
-	WrapCheckBool ( found, zXMPMeta_GetArrayItem_1 ( schemaNS, arrayName, itemIndex, &resultPtr, &resultLen, options ) );
-	if ( found ) {
-		if ( itemValue != 0 ) itemValue->assign ( resultPtr, resultLen );
-		WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 );
-	}
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetStructField ( XMP_StringPtr    schemaNS,
-                 XMP_StringPtr    structName,
-				 XMP_StringPtr    fieldNS,
-				 XMP_StringPtr    fieldName,
-				 tStringObj *     fieldValue,
-				 XMP_OptionBits * options ) const
-{
-	XMP_StringPtr resultPtr = 0;
-	XMP_StringLen resultLen = 0;
-	WrapCheckBool ( found, zXMPMeta_GetStructField_1 ( schemaNS, structName, fieldNS, fieldName, &resultPtr, &resultLen, options ) );
-	if ( found ) {
-		if ( fieldValue != 0 ) fieldValue->assign ( resultPtr, resultLen );
-		WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 );
-	}
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetQualifier ( XMP_StringPtr    schemaNS,
-               XMP_StringPtr    propName,
-			   XMP_StringPtr    qualNS,
-			   XMP_StringPtr    qualName,
-			   tStringObj *     qualValue,
-			   XMP_OptionBits * options ) const
-{
-	XMP_StringPtr resultPtr = 0;
-	XMP_StringLen resultLen = 0;
-	WrapCheckBool ( found, zXMPMeta_GetQualifier_1 ( schemaNS, propName, qualNS, qualName, &resultPtr, &resultLen, options ) );
-	if ( found ) {
-		if ( qualValue != 0 ) qualValue->assign ( resultPtr, resultLen );
-		WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 );
-	}
-	return found;
-}	//GetQualifier ()
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetProperty ( XMP_StringPtr  schemaNS,
-              XMP_StringPtr  propName,
-			  XMP_StringPtr  propValue,
-			  XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_SetProperty_1 ( schemaNS, propName, propValue, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetProperty ( XMP_StringPtr      schemaNS,
-              XMP_StringPtr      propName,
-			  const tStringObj & propValue,
-			  XMP_OptionBits     options /* = 0 */ )
-{
-	this->SetProperty ( schemaNS, propName, propValue.c_str(), options );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetArrayItem ( XMP_StringPtr  schemaNS,
-               XMP_StringPtr  arrayName,
-               XMP_Index      itemIndex,
-			   XMP_StringPtr  itemValue,
-			   XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_SetArrayItem_1 ( schemaNS, arrayName, itemIndex, itemValue, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetArrayItem ( XMP_StringPtr      schemaNS,
-               XMP_StringPtr      arrayName,
-               XMP_Index          itemIndex,
-			   const tStringObj & itemValue,
-			   XMP_OptionBits     options /* = 0 */ )
-{
-	this->SetArrayItem ( schemaNS, arrayName, itemIndex, itemValue.c_str(), options );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-AppendArrayItem ( XMP_StringPtr  schemaNS,
-                  XMP_StringPtr  arrayName,
-                  XMP_OptionBits arrayOptions,
-				  XMP_StringPtr  itemValue,
-				  XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_AppendArrayItem_1 ( schemaNS, arrayName, arrayOptions, itemValue, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-AppendArrayItem ( XMP_StringPtr      schemaNS,
-                  XMP_StringPtr      arrayName,
-                  XMP_OptionBits     arrayOptions,
-				  const tStringObj & itemValue,
-				  XMP_OptionBits     options /* = 0 */ )
-{
-	this->AppendArrayItem ( schemaNS, arrayName, arrayOptions, itemValue.c_str(), options );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetStructField ( XMP_StringPtr  schemaNS,
-                 XMP_StringPtr  structName,
-				 XMP_StringPtr  fieldNS,
-				 XMP_StringPtr  fieldName,
-				 XMP_StringPtr  fieldValue,
-				 XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_SetStructField_1 ( schemaNS, structName, fieldNS, fieldName, fieldValue, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetStructField ( XMP_StringPtr      schemaNS,
-                 XMP_StringPtr      structName,
-				 XMP_StringPtr      fieldNS,
-				 XMP_StringPtr      fieldName,
-				 const tStringObj & fieldValue,
-				 XMP_OptionBits     options /* = 0 */ )
-{
-	this->SetStructField ( schemaNS, structName, fieldNS, fieldName, fieldValue.c_str(), options );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetQualifier ( XMP_StringPtr  schemaNS,
-               XMP_StringPtr  propName,
-			   XMP_StringPtr  qualNS,
-			   XMP_StringPtr  qualName,
-			   XMP_StringPtr  qualValue,
-			   XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_SetQualifier_1 ( schemaNS, propName, qualNS, qualName, qualValue, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetQualifier ( XMP_StringPtr      schemaNS,
-               XMP_StringPtr      propName,
-			   XMP_StringPtr      qualNS,
-			   XMP_StringPtr      qualName,
-			   const tStringObj & qualValue,
-			   XMP_OptionBits     options /* = 0 */ )
-{
-	this->SetQualifier ( schemaNS, propName, qualNS, qualName, qualValue.c_str(), options );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-DeleteProperty ( XMP_StringPtr schemaNS,
-                 XMP_StringPtr propName )
-{
-	WrapCheckVoid ( zXMPMeta_DeleteProperty_1 ( schemaNS, propName ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-DeleteArrayItem ( XMP_StringPtr schemaNS,
-                  XMP_StringPtr arrayName,
-                  XMP_Index     itemIndex )
-{
-	WrapCheckVoid ( zXMPMeta_DeleteArrayItem_1 ( schemaNS, arrayName, itemIndex ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-DeleteStructField ( XMP_StringPtr schemaNS,
-                    XMP_StringPtr structName,
-					XMP_StringPtr fieldNS,
-					XMP_StringPtr fieldName )
-{
-	WrapCheckVoid ( zXMPMeta_DeleteStructField_1 ( schemaNS, structName, fieldNS, fieldName ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-DeleteQualifier ( XMP_StringPtr schemaNS,
-                  XMP_StringPtr propName,
-				  XMP_StringPtr qualNS,
-				  XMP_StringPtr qualName )
-{
-	WrapCheckVoid ( zXMPMeta_DeleteQualifier_1 ( schemaNS, propName, qualNS, qualName ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-DoesPropertyExist ( XMP_StringPtr schemaNS,
-                    XMP_StringPtr propName ) const
-{
-	WrapCheckBool ( exists, zXMPMeta_DoesPropertyExist_1 ( schemaNS, propName ) );
-	return exists;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-DoesArrayItemExist ( XMP_StringPtr schemaNS,
-                     XMP_StringPtr arrayName,
-                     XMP_Index itemIndex ) const
-{
-	WrapCheckBool ( exists, zXMPMeta_DoesArrayItemExist_1 ( schemaNS, arrayName, itemIndex ) );
-	return exists;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-DoesStructFieldExist ( XMP_StringPtr schemaNS,
-                       XMP_StringPtr structName,
-					   XMP_StringPtr fieldNS,
-					   XMP_StringPtr fieldName ) const
-{
-	WrapCheckBool ( exists, zXMPMeta_DoesStructFieldExist_1 ( schemaNS, structName, fieldNS, fieldName ) );
-	return exists;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-DoesQualifierExist ( XMP_StringPtr schemaNS,
-                     XMP_StringPtr propName,
-					 XMP_StringPtr qualNS,
-					 XMP_StringPtr qualName ) const
-{
-	WrapCheckBool ( exists, zXMPMeta_DoesQualifierExist_1 ( schemaNS, propName, qualNS, qualName ) );
-	return exists;
-}
-
-// =================================================================================================
-// Specialized Get and Set functions
-// =================================
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetLocalizedText ( XMP_StringPtr    schemaNS,
-                   XMP_StringPtr    altTextName,
-				   XMP_StringPtr    genericLang,
-				   XMP_StringPtr    specificLang,
-				   tStringObj *     actualLang,
-				   tStringObj *     itemValue,
-				   XMP_OptionBits * options ) const
-{
-	XMP_StringPtr langPtr = 0;
-	XMP_StringLen langLen = 0;
-	XMP_StringPtr itemPtr = 0;
-	XMP_StringLen itemLen = 0;
-	WrapCheckBool ( found, zXMPMeta_GetLocalizedText_1 ( schemaNS, altTextName, genericLang, specificLang,
-														 &langPtr, &langLen, &itemPtr, &itemLen, options ) );
-	if ( found ) {
-		if ( actualLang != 0 ) actualLang->assign ( langPtr, langLen );
-		if ( itemValue != 0 ) itemValue->assign ( itemPtr, itemLen );
-		WXMPMeta_UnlockObject_1 ( this->xmpRef, kXMP_NoOptions );
-	}
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetLocalizedText ( XMP_StringPtr  schemaNS,
-                   XMP_StringPtr  altTextName,
-				   XMP_StringPtr  genericLang,
-				   XMP_StringPtr  specificLang,
-				   XMP_StringPtr  itemValue,
-				   XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_SetLocalizedText_1 ( schemaNS, altTextName, genericLang, specificLang, itemValue, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetLocalizedText ( XMP_StringPtr      schemaNS,
-                   XMP_StringPtr      altTextName,
-				   XMP_StringPtr      genericLang,
-				   XMP_StringPtr      specificLang,
-				   const tStringObj & itemValue,
-				   XMP_OptionBits     options /* = 0 */ )
-{
-	this->SetLocalizedText ( schemaNS, altTextName, genericLang, specificLang, itemValue.c_str(), options );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetProperty_Bool ( XMP_StringPtr    schemaNS,
-                   XMP_StringPtr    propName,
-				   bool *           propValue,
-				   XMP_OptionBits * options ) const
-{
-	XMP_Bool binValue;
-	WrapCheckBool ( found, zXMPMeta_GetProperty_Bool_1 ( schemaNS, propName, &binValue, options ) );
-	if ( found && (propValue != 0) ) *propValue = binValue;
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetProperty_Int ( XMP_StringPtr    schemaNS,
-                  XMP_StringPtr    propName,
-				  long *           propValue,
-				  XMP_OptionBits * options ) const
-{
-	XMP_Int32 abiValue;
-	WrapCheckBool ( found, zXMPMeta_GetProperty_Int_1 ( schemaNS, propName, &abiValue, options ) );
-	if ( found && (propValue != 0) ) *propValue = abiValue;
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetProperty_Int64 ( XMP_StringPtr    schemaNS,
-                    XMP_StringPtr    propName,
-				    long long *      propValue,
-				    XMP_OptionBits * options ) const
-{
-	XMP_Int64 abiValue;
-	WrapCheckBool ( found, zXMPMeta_GetProperty_Int64_1 ( schemaNS, propName, &abiValue, options ) );
-	if ( found && (propValue != 0) ) *propValue = abiValue;
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetProperty_Float ( XMP_StringPtr    schemaNS,
-                    XMP_StringPtr    propName,
-					double *         propValue,
-					XMP_OptionBits * options ) const
-{
-	WrapCheckBool ( found, zXMPMeta_GetProperty_Float_1 ( schemaNS, propName, propValue, options ) );
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,bool)::
-GetProperty_Date ( XMP_StringPtr    schemaNS,
-                   XMP_StringPtr    propName,
-				   XMP_DateTime *   propValue,
-				   XMP_OptionBits * options ) const
-{
-	WrapCheckBool ( found, zXMPMeta_GetProperty_Date_1 ( schemaNS, propName, propValue, options ) );
-	return found;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetProperty_Bool ( XMP_StringPtr  schemaNS,
-                   XMP_StringPtr  propName,
-				   bool           propValue,
-				   XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_SetProperty_Bool_1 ( schemaNS, propName, propValue, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetProperty_Int ( XMP_StringPtr  schemaNS,
-                  XMP_StringPtr  propName,
-				  long           propValue,
-				  XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_SetProperty_Int_1 ( schemaNS, propName, propValue, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetProperty_Int64 ( XMP_StringPtr  schemaNS,
-                    XMP_StringPtr  propName,
-				    long long      propValue,
-				    XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_SetProperty_Int64_1 ( schemaNS, propName, propValue, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetProperty_Float ( XMP_StringPtr  schemaNS,
-                    XMP_StringPtr  propName,
-					double         propValue,
-					XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_SetProperty_Float_1 ( schemaNS, propName, propValue, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetProperty_Date ( XMP_StringPtr        schemaNS,
-                   XMP_StringPtr        propName,
-				   const XMP_DateTime &	propValue,
-				   XMP_OptionBits       options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_SetProperty_Date_1 ( schemaNS, propName, propValue, options ) );
-}
-
-// =================================================================================================
-// Miscellaneous Member Functions
-// ==============================
-
-XMP_MethodIntro(TXMPMeta,XMPMetaRef)::
-GetInternalRef() const
-{
-	return this->xmpRef;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-GetObjectName ( tStringObj * name ) const
-{
-	XMP_StringPtr namePtr = 0;
-	XMP_StringLen nameLen = 0;
-	WrapCheckVoid ( zXMPMeta_GetObjectName_1 ( &namePtr, &nameLen ) );
-	if ( name != 0 ) name->assign ( namePtr, nameLen );
-	WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetObjectName ( XMP_StringPtr name )
-{
-	WrapCheckVoid ( zXMPMeta_SetObjectName_1 ( name ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetObjectName ( tStringObj name )
-{
-	this->SetObjectName ( name.c_str() );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,XMP_OptionBits)::
-GetObjectOptions() const
-{
-	WrapCheckOptions ( options, zXMPMeta_GetObjectOptions_1() );
-	return options;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SetObjectOptions ( XMP_OptionBits options )
-{
-	WrapCheckVoid ( zXMPMeta_SetObjectOptions_1 ( options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-Sort()
-{
-	WrapCheckVoid ( zXMPMeta_Sort_1() );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-Erase()
-{
-	WrapCheckVoid ( zXMPMeta_Erase_1() );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,TXMPMeta<tStringObj>)::
-Clone ( XMP_OptionBits options ) const
-{
-	WrapCheckMetaRef ( cloneRef, zXMPMeta_Clone_1 ( options ) );
-	return TXMPMeta<tStringObj> ( cloneRef );	// Ref construct will increment the clientRefs.
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,XMP_Index)::
-CountArrayItems ( XMP_StringPtr schemaNS,
-                  XMP_StringPtr arrayName ) const
-{
-	WrapCheckIndex ( count, zXMPMeta_CountArrayItems_1 ( schemaNS, arrayName ) );
-	return count;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,XMP_Status)::
-DumpObject ( XMP_TextOutputProc outProc,
-             void *             refCon ) const
-{
-	TOPW_Info info ( outProc, refCon );
-	WrapCheckStatus ( status, zXMPMeta_DumpObject_1 ( TextOutputProcWrapper, &info ) );
-	return status;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-ParseFromBuffer ( XMP_StringPtr  buffer,
-                  XMP_StringLen  bufferSize,
-                  XMP_OptionBits options /* = 0 */ )
-{
-	WrapCheckVoid ( zXMPMeta_ParseFromBuffer_1 ( buffer, bufferSize, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SerializeToBuffer ( tStringObj *   pktString,
-                    XMP_OptionBits options,
-                    XMP_StringLen  padding,
-					XMP_StringPtr  newline,
-					XMP_StringPtr  indent,
-					XMP_Index      baseIndent /* = 0 */ ) const
-{
-	XMP_StringPtr resultPtr = 0;
-	XMP_StringLen resultLen = 0;
-	WrapCheckVoid ( zXMPMeta_SerializeToBuffer_1 ( &resultPtr, &resultLen, options, padding, newline, indent, baseIndent ) );
-	if ( pktString != 0 ) pktString->assign ( resultPtr, resultLen );
-	WXMPMeta_UnlockObject_1 ( this->xmpRef, 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPMeta,void)::
-SerializeToBuffer ( tStringObj *   pktString,
-					XMP_OptionBits options /* = 0 */,
-					XMP_StringLen  padding /* = 0 */ ) const
-{
-	this->SerializeToBuffer ( pktString, options, padding, "", "", 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-// =================================================================================================
diff --git a/xmpsdk/include/client-glue/TXMPUtils.incl_cpp b/xmpsdk/include/client-glue/TXMPUtils.incl_cpp
deleted file mode 100644
index 6898be73..00000000
--- a/xmpsdk/include/client-glue/TXMPUtils.incl_cpp
+++ /dev/null
@@ -1,493 +0,0 @@
-// =================================================================================================
-// ADOBE SYSTEMS INCORPORATED
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved
-//
-// NOTICE:	Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-//	================================================================================================
-/// \file TXMPUtils.incl_cpp
-/// \brief The implementation of the TXMPUtils template class.
-
-#include "XMPSDK.hpp"
-#include "client-glue/WXMP_Common.hpp"
-#include "client-glue/WXMPUtils.hpp"
-
-// =================================================================================================
-// Implementation Guidelines
-// =========================
-//
-// The implementations of the template functions are very stylized. ...
-//
-// =================================================================================================
-
-XMP_MethodIntro(TXMPUtils,void)::
-ComposeArrayItemPath ( XMP_StringPtr schemaNS,
-					   XMP_StringPtr arrayName,
-					   XMP_Index	 itemIndex,
-					   tStringObj *  fullPath )
-{
-	XMP_StringPtr pathPtr = 0;
-	XMP_StringLen pathLen = 0;
-	WrapCheckVoid ( zXMPUtils_ComposeArrayItemPath_1 ( schemaNS, arrayName, itemIndex, &pathPtr, &pathLen ) );
-	if ( fullPath != 0 ) fullPath->assign ( pathPtr, pathLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ComposeStructFieldPath ( XMP_StringPtr schemaNS,
-						 XMP_StringPtr structName,
-						 XMP_StringPtr fieldNS,
-						 XMP_StringPtr fieldName,
-						 tStringObj *  fullPath )
-{
-	XMP_StringPtr pathPtr = 0;
-	XMP_StringLen pathLen = 0;
-	WrapCheckVoid ( zXMPUtils_ComposeStructFieldPath_1 ( schemaNS, structName, fieldNS, fieldName, &pathPtr, &pathLen ) );
-	if ( fullPath != 0 ) fullPath->assign ( pathPtr, pathLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ComposeQualifierPath ( XMP_StringPtr schemaNS,
-					   XMP_StringPtr propName,
-					   XMP_StringPtr qualNS,
-					   XMP_StringPtr qualName,
-					   tStringObj *	 fullPath )
-{
-	XMP_StringPtr pathPtr = 0;
-	XMP_StringLen pathLen = 0;
-	WrapCheckVoid ( zXMPUtils_ComposeQualifierPath_1 ( schemaNS, propName, qualNS, qualName, &pathPtr, &pathLen ) );
-	if ( fullPath != 0 ) fullPath->assign ( pathPtr, pathLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ComposeLangSelector ( XMP_StringPtr schemaNS,
-					  XMP_StringPtr arrayName,
-					  XMP_StringPtr langName,
-					  tStringObj *	fullPath )
-{
-	XMP_StringPtr pathPtr = 0;
-	XMP_StringLen pathLen = 0;
-	WrapCheckVoid ( zXMPUtils_ComposeLangSelector_1 ( schemaNS, arrayName, langName, &pathPtr, &pathLen ) );
-	if ( fullPath != 0 ) fullPath->assign ( pathPtr, pathLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ComposeLangSelector ( XMP_StringPtr		 schemaNS,
-					  XMP_StringPtr		 arrayName,
-					  const tStringObj & langName,
-					  tStringObj *		 fullPath )
-{
-	TXMPUtils::ComposeLangSelector ( schemaNS, arrayName, langName.c_str(), fullPath );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ComposeFieldSelector ( XMP_StringPtr schemaNS,
-					   XMP_StringPtr arrayName,
-					   XMP_StringPtr fieldNS,
-					   XMP_StringPtr fieldName,
-					   XMP_StringPtr fieldValue,
-					   tStringObj *	 fullPath )
-{
-	XMP_StringPtr pathPtr = 0;
-	XMP_StringLen pathLen = 0;
-	WrapCheckVoid ( zXMPUtils_ComposeFieldSelector_1 ( schemaNS, arrayName, fieldNS, fieldName, fieldValue,
-													   &pathPtr, &pathLen ) );
-	if ( fullPath != 0 ) fullPath->assign ( pathPtr, pathLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ComposeFieldSelector ( XMP_StringPtr	  schemaNS,
-					   XMP_StringPtr	  arrayName,
-					   XMP_StringPtr	  fieldNS,
-					   XMP_StringPtr	  fieldName,
-					   const tStringObj & fieldValue,
-					   tStringObj *		  fullPath )
-{
-	TXMPUtils::ComposeFieldSelector ( schemaNS, arrayName, fieldNS, fieldName, fieldValue.c_str(), fullPath );
-}
-
-// -------------------------------------------------------------------------------------------------
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ConvertFromBool ( bool		   binValue,
-				  tStringObj * strValue )
-{
-	XMP_StringPtr strPtr = 0;
-	XMP_StringLen strLen = 0;
-	WrapCheckVoid ( zXMPUtils_ConvertFromBool_1 ( binValue, &strPtr, &strLen ) );
-	if ( strValue != 0 ) strValue->assign ( strPtr, strLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ConvertFromInt ( long		   binValue,
-				 XMP_StringPtr format,
-				 tStringObj *  strValue )
-{
-	XMP_StringPtr strPtr = 0;
-	XMP_StringLen strLen = 0;
-	WrapCheckVoid ( zXMPUtils_ConvertFromInt_1 ( binValue, format, &strPtr, &strLen ) );
-	if ( strValue != 0 ) strValue->assign ( strPtr, strLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ConvertFromInt64 ( long long 	 binValue,
-				   XMP_StringPtr format,
-				   tStringObj *  strValue )
-{
-	XMP_StringPtr strPtr = 0;
-	XMP_StringLen strLen = 0;
-	WrapCheckVoid ( zXMPUtils_ConvertFromInt64_1 ( binValue, format, &strPtr, &strLen ) );
-	if ( strValue != 0 ) strValue->assign ( strPtr, strLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ConvertFromFloat ( double		 binValue,
-				   XMP_StringPtr format,
-				   tStringObj *	 strValue )
-{
-	XMP_StringPtr strPtr = 0;
-	XMP_StringLen strLen = 0;
-	WrapCheckVoid ( zXMPUtils_ConvertFromFloat_1 ( binValue, format, &strPtr, &strLen ) );
-	if ( strValue != 0 ) strValue->assign ( strPtr, strLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ConvertFromDate ( const XMP_DateTime & binValue,
-				  tStringObj *		   strValue )
-{
-	XMP_StringPtr strPtr = 0;
-	XMP_StringLen strLen = 0;
-	WrapCheckVoid ( zXMPUtils_ConvertFromDate_1 ( binValue, &strPtr, &strLen ) );
-	if ( strValue != 0 ) strValue->assign ( strPtr, strLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,bool)::
-ConvertToBool ( XMP_StringPtr strValue )
-{
-	WrapCheckBool ( value, zXMPUtils_ConvertToBool_1 ( strValue ) );
-	return value;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,bool)::
-ConvertToBool ( const tStringObj & strValue )
-{
-	return TXMPUtils::ConvertToBool ( strValue.c_str() );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,long)::
-ConvertToInt ( XMP_StringPtr strValue )
-{
-	WrapCheckInt32 ( value, zXMPUtils_ConvertToInt_1 ( strValue ) );
-	return value;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,long)::
-ConvertToInt ( const tStringObj & strValue )
-{
-	return TXMPUtils::ConvertToInt ( strValue.c_str() );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,long long)::
-ConvertToInt64 ( XMP_StringPtr strValue )
-{
-	WrapCheckInt64 ( value, zXMPUtils_ConvertToInt64_1 ( strValue ) );
-	return value;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,long long)::
-ConvertToInt64 ( const tStringObj & strValue )
-{
-	return TXMPUtils::ConvertToInt64 ( strValue.c_str() );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,double)::
-ConvertToFloat ( XMP_StringPtr strValue )
-{
-	WrapCheckFloat ( value, zXMPUtils_ConvertToFloat_1 ( strValue ) );
-	return value;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,double)::
-ConvertToFloat ( const tStringObj & strValue )
-{
-	return TXMPUtils::ConvertToFloat ( strValue.c_str() );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ConvertToDate ( XMP_StringPtr  strValue,
-				XMP_DateTime * binValue )
-{
-	WrapCheckVoid ( zXMPUtils_ConvertToDate_1 ( strValue, binValue ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ConvertToDate ( const tStringObj & strValue,
-				XMP_DateTime *	   binValue )
-{
-	TXMPUtils::ConvertToDate ( strValue.c_str(), binValue );
-}
-
-// -------------------------------------------------------------------------------------------------
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-CurrentDateTime ( XMP_DateTime * time )
-{
-	WrapCheckVoid ( zXMPUtils_CurrentDateTime_1 ( time ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-SetTimeZone ( XMP_DateTime * time )
-{
-	WrapCheckVoid ( zXMPUtils_SetTimeZone_1 ( time ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ConvertToUTCTime ( XMP_DateTime * time )
-{
-	WrapCheckVoid ( zXMPUtils_ConvertToUTCTime_1 ( time ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-ConvertToLocalTime ( XMP_DateTime * time )
-{
-	WrapCheckVoid ( zXMPUtils_ConvertToLocalTime_1 ( time ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,int)::
-CompareDateTime ( const XMP_DateTime & left,
-				  const XMP_DateTime & right )
-{
-	WrapCheckInt32 ( result, zXMPUtils_CompareDateTime_1 ( left, right ) );
-	return result;
-}
-
-// -------------------------------------------------------------------------------------------------
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-EncodeToBase64 ( XMP_StringPtr rawStr,
-				 XMP_StringLen rawLen,
-				 tStringObj *  encodedStr )
-{
-	XMP_StringPtr encPtr = 0;
-	XMP_StringLen encLen = 0;
-	WrapCheckVoid ( zXMPUtils_EncodeToBase64_1 ( rawStr, rawLen, &encPtr, &encLen ) );
-	if ( encodedStr != 0 ) encodedStr->assign ( encPtr, encLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-EncodeToBase64 ( const tStringObj & rawStr,
-				 tStringObj *		encodedStr )
-{
-	TXMPUtils::EncodeToBase64 ( rawStr.c_str(), (XMP_StringLen)rawStr.size(), encodedStr );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-DecodeFromBase64 ( XMP_StringPtr encodedStr,
-				   XMP_StringLen encodedLen,
-				   tStringObj *	 rawStr )
-{
-	XMP_StringPtr rawPtr = 0;
-	XMP_StringLen rawLen = 0;
-	WrapCheckVoid ( zXMPUtils_DecodeFromBase64_1 ( encodedStr, encodedLen, &rawPtr, &rawLen ) );
-	if ( rawStr != 0 ) rawStr->assign ( rawPtr, rawLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-DecodeFromBase64 ( const tStringObj & encodedStr,
-				   tStringObj *		  rawStr )
-{
-	TXMPUtils::DecodeFromBase64 ( encodedStr.c_str(), (XMP_StringLen)encodedStr.size(), rawStr );
-}
-
-// -------------------------------------------------------------------------------------------------
-// -------------------------------------------------------------------------------------------------
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-PackageForJPEG ( const TXMPMeta<tStringObj> & xmpObj,
-                 tStringObj * standardXMP,
-                 tStringObj * extendedXMP,
-                 tStringObj * extendedDigest )
-{
-	XMP_StringPtr stdStr = 0;
-	XMP_StringLen stdLen = 0;
-	XMP_StringPtr extStr = 0;
-	XMP_StringLen extLen = 0;
-	XMP_StringPtr digestStr = 0;
-	XMP_StringLen digestLen = 0;
-	WrapCheckVoid ( zXMPUtils_PackageForJPEG_1 ( xmpObj.GetInternalRef(),
-	                                             &stdStr, &stdLen, &extStr, &extLen, &digestStr, &digestLen ) );
-	if ( standardXMP != 0 ) standardXMP->assign ( stdStr, stdLen );
-	if ( extendedXMP != 0 ) extendedXMP->assign ( extStr, extLen );
-	if ( extendedDigest != 0 ) extendedDigest->assign ( digestStr, digestLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-MergeFromJPEG ( TXMPMeta<tStringObj> * fullXMP,
-                const TXMPMeta<tStringObj> & extendedXMP )
-{
-	WrapCheckVoid ( zXMPUtils_MergeFromJPEG_1 ( fullXMP->GetInternalRef(), extendedXMP.GetInternalRef() ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-CatenateArrayItems ( const TXMPMeta<tStringObj> & xmpObj,
-					 XMP_StringPtr	schemaNS,
-					 XMP_StringPtr	arrayName,
-					 XMP_StringPtr	separator,
-					 XMP_StringPtr	quotes,
-					 XMP_OptionBits options,
-					 tStringObj *	catedStr )
-{
-	XMP_StringPtr catedPtr = 0;
-	XMP_StringLen catedLen = 0;
-	WrapCheckVoid ( zXMPUtils_CatenateArrayItems_1 ( xmpObj.GetInternalRef(), schemaNS, arrayName, 
-													 separator, quotes, options, &catedPtr, &catedLen ) );
-	if ( catedStr != 0 ) catedStr->assign ( catedPtr, catedLen );
-	WXMPUtils_Unlock_1 ( 0 );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-SeparateArrayItems ( TXMPMeta<tStringObj> * xmpObj,
-					 XMP_StringPtr	schemaNS,
-					 XMP_StringPtr	arrayName,
-					 XMP_OptionBits options,
-					 XMP_StringPtr	catedStr )
-{
-	if ( xmpObj == 0 ) throw XMP_Error ( kXMPErr_BadParam, "Null output SXMPMeta pointer" );
-	WrapCheckVoid ( zXMPUtils_SeparateArrayItems_1 ( xmpObj->GetInternalRef(), schemaNS, arrayName, options, catedStr ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-SeparateArrayItems ( TXMPMeta<tStringObj> * xmpObj,
-					 XMP_StringPtr		schemaNS,
-					 XMP_StringPtr		arrayName,
-					 XMP_OptionBits		options,
-					 const tStringObj & catedStr )
-{
-	TXMPUtils::SeparateArrayItems ( xmpObj, schemaNS, arrayName, options, catedStr.c_str() );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-RemoveProperties ( TXMPMeta<tStringObj> * xmpObj,
-				   XMP_StringPtr  schemaNS /* = 0 */,
-				   XMP_StringPtr  propName /* = 0 */,
-				   XMP_OptionBits options /* = 0 */ )
-{
-	if ( xmpObj == 0 ) throw XMP_Error ( kXMPErr_BadParam, "Null output SXMPMeta pointer" );
-	WrapCheckVoid ( zXMPUtils_RemoveProperties_1 ( xmpObj->GetInternalRef(), schemaNS, propName, options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-AppendProperties ( const TXMPMeta<tStringObj> & source,
-				   TXMPMeta<tStringObj> *		dest,
-				   XMP_OptionBits options /* = 0 */ )
-{
-	if ( dest == 0 ) throw XMP_Error ( kXMPErr_BadParam, "Null output SXMPMeta pointer" );
-	WrapCheckVoid ( zXMPUtils_AppendProperties_1 ( source.GetInternalRef(), dest->GetInternalRef(), options ) );
-}
-
-// -------------------------------------------------------------------------------------------------
-
-XMP_MethodIntro(TXMPUtils,void)::
-DuplicateSubtree ( const TXMPMeta<tStringObj> & source,
-				   TXMPMeta<tStringObj> *		dest,
-				   XMP_StringPtr  sourceNS,
-				   XMP_StringPtr  sourceRoot,
-				   XMP_StringPtr  destNS /*= 0 */,
-				   XMP_StringPtr  destRoot /* = 0 */,
-				   XMP_OptionBits options /* = 0 */ )
-{
-	if ( dest == 0 ) throw XMP_Error ( kXMPErr_BadParam, "Null output SXMPMeta pointer" );
-	WrapCheckVoid ( zXMPUtils_DuplicateSubtree_1 ( source.GetInternalRef(), dest->GetInternalRef(),
-												   sourceNS, sourceRoot, destNS, destRoot, options ) );
-}
-
-// =================================================================================================
-
-// =================================================================================================
diff --git a/xmpsdk/include/client-glue/WXMPFiles.hpp b/xmpsdk/include/client-glue/WXMPFiles.hpp
deleted file mode 100644
index cdc510ce..00000000
--- a/xmpsdk/include/client-glue/WXMPFiles.hpp
+++ /dev/null
@@ -1,167 +0,0 @@
-#ifndef __WXMPFiles_hpp__
-#define __WXMPFiles_hpp__	1
-
-// =================================================================================================
-// ADOBE SYSTEMS INCORPORATED
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved
-//
-// NOTICE: Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "client-glue/WXMP_Common.hpp"
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// =================================================================================================
-/// \file WXMPFiles.h
-/// \brief High level support to access metadata in files of interest to Adobe applications.
-///
-/// This header ...
-///
-// =================================================================================================
-
-// =================================================================================================
-
-#define WrapCheckXMPFilesRef(result,WCallProto) \
-    WXMP_Result wResult;                        \
-    WCallProto;                                 \
-    PropagateException ( wResult );             \
-    XMPFilesRef result = XMPFilesRef(wResult.ptrResult)
-
-// =================================================================================================
-
-#define zXMPFiles_GetVersionInfo_1(versionInfo) \
-	WXMPFiles_GetVersionInfo_1 ( versionInfo /* no wResult */ )
-
-#define zXMPFiles_Initialize_1() \
-	WXMPFiles_Initialize_1 ( &wResult )
-
-#define zXMPFiles_Initialize_2(options) \
-	WXMPFiles_Initialize_2 ( options, &wResult )
-
-#define zXMPFiles_Terminate_1() \
-	WXMPFiles_Terminate_1 ( /* no wResult */ )
-
-#define zXMPFiles_CTor_1() \
-	WXMPFiles_CTor_1 ( &wResult )
-
-#define zXMPFiles_GetFormatInfo_1(format,flags) \
-	WXMPFiles_GetFormatInfo_1 ( format, flags, &wResult )
-
-#define zXMPFiles_CheckFileFormat_1(filePath) \
-	WXMPFiles_CheckFileFormat_1 ( filePath, &wResult )
-
-#define zXMPFiles_CheckPackageFormat_1(folderPath) \
-	WXMPFiles_CheckPackageFormat_1 ( folderPath, &wResult )
-
-#define zXMPFiles_OpenFile_1(filePath,format,openFlags) \
-	WXMPFiles_OpenFile_1 ( this->xmpFilesRef, filePath, format, openFlags, &wResult )
-    
-#define zXMPFiles_CloseFile_1(closeFlags) \
-	WXMPFiles_CloseFile_1 ( this->xmpFilesRef, closeFlags, &wResult )
-	
-#define zXMPFiles_GetFileInfo_1(filePath,filePathLen,openFlags,format,handlerFlags) \
-	WXMPFiles_GetFileInfo_1 ( this->xmpFilesRef, filePath, filePathLen, openFlags, format, handlerFlags, &wResult )
-    
-#define zXMPFiles_SetAbortProc_1(abortProc,abortArg) \
-	WXMPFiles_SetAbortProc_1 ( this->xmpFilesRef, abortProc, abortArg, &wResult )
-    
-#define zXMPFiles_GetXMP_1(xmpRef,xmpPacket,xmpPacketLen,packetInfo) \
-	WXMPFiles_GetXMP_1 ( this->xmpFilesRef, xmpRef, xmpPacket, xmpPacketLen, packetInfo, &wResult )
-    
-#define zXMPFiles_GetThumbnail_1(tnailInfo) \
-	WXMPFiles_GetThumbnail_1 ( this->xmpFilesRef, tnailInfo, &wResult )
-    
-#define zXMPFiles_PutXMP_1(xmpRef,xmpPacket,xmpPacketLen) \
-	WXMPFiles_PutXMP_1 ( this->xmpFilesRef, xmpRef, xmpPacket, xmpPacketLen, &wResult )
-    
-#define zXMPFiles_CanPutXMP_1(xmpRef,xmpPacket,xmpPacketLen) \
-	WXMPFiles_CanPutXMP_1 ( this->xmpFilesRef, xmpRef, xmpPacket, xmpPacketLen, &wResult )
-
-// =================================================================================================
-
-extern void WXMPFiles_GetVersionInfo_1 ( XMP_VersionInfo * versionInfo );
-
-extern void WXMPFiles_Initialize_1 ( WXMP_Result * result );
-
-extern void WXMPFiles_Initialize_2 ( XMP_OptionBits options, WXMP_Result * result );
-
-extern void WXMPFiles_Terminate_1();
-
-extern void WXMPFiles_CTor_1 ( WXMP_Result * result );
-
-extern void WXMPFiles_UnlockLib_1();
-
-extern void WXMPFiles_UnlockObj_1 ( XMPFilesRef xmpFilesRef );
-
-extern void WXMPFiles_IncrementRefCount_1 ( XMPFilesRef xmpFilesRef );
-
-extern void WXMPFiles_DecrementRefCount_1 ( XMPFilesRef xmpFilesRef );
-
-extern void WXMPFiles_GetFormatInfo_1 ( XMP_FileFormat   format,
-                                        XMP_OptionBits * flags,	// ! Can be null.
-                                        WXMP_Result *    result );
-
-extern void WXMPFiles_CheckFileFormat_1 ( XMP_StringPtr filePath,
-                               			  WXMP_Result * result );
-
-extern void WXMPFiles_CheckPackageFormat_1 ( XMP_StringPtr folderPath,
-                      						 WXMP_Result * result );
-
-extern void WXMPFiles_OpenFile_1 ( XMPFilesRef    xmpFilesRef,
-                                   XMP_StringPtr  filePath,
-					               XMP_FileFormat format,
-					               XMP_OptionBits openFlags,
-                                   WXMP_Result *  result );
-    
-extern void WXMPFiles_CloseFile_1 ( XMPFilesRef    xmpFilesRef,
-                                    XMP_OptionBits closeFlags,
-                                    WXMP_Result *  result );
-	
-extern void WXMPFiles_GetFileInfo_1 ( XMPFilesRef      xmpFilesRef,
-                                      XMP_StringPtr *  filePath,
-                                      XMP_StringLen *  filePathLen,
-					                  XMP_OptionBits * openFlags,		// ! Can be null.
-					                  XMP_FileFormat * format,		// ! Can be null.
-					                  XMP_OptionBits * handlerFlags,	// ! Can be null.
-                                      WXMP_Result *    result );
-    
-extern void WXMPFiles_SetAbortProc_1 ( XMPFilesRef   xmpFilesRef,
-                                       XMP_AbortProc abortProc,
-									   void *        abortArg,
-                                       WXMP_Result * result );
-    
-extern void WXMPFiles_GetXMP_1 ( XMPFilesRef      xmpFilesRef,
-                                 XMPMetaRef       xmpRef,		// ! Can be null.
-    			                 XMP_StringPtr *  xmpPacket,
-    			                 XMP_StringLen *  xmpPacketLen,
-    			                 XMP_PacketInfo * packetInfo,	// ! Can be null.
-                                 WXMP_Result *    result );
-    
-extern void WXMPFiles_GetThumbnail_1 ( XMPFilesRef         xmpFilesRef,
-    			                       XMP_ThumbnailInfo * tnailInfo,	// ! Can be null.
-                                       WXMP_Result *       result );
-    
-extern void WXMPFiles_PutXMP_1 ( XMPFilesRef   xmpFilesRef,
-                                 XMPMetaRef    xmpRef,		// ! Only one of the XMP object or packet are passed.
-                                 XMP_StringPtr xmpPacket,
-                                 XMP_StringLen xmpPacketLen,
-                                 WXMP_Result * result );
-    
-extern void WXMPFiles_CanPutXMP_1 ( XMPFilesRef   xmpFilesRef,
-                                    XMPMetaRef	  xmpRef,		// ! Only one of the XMP object or packet are passed.
-                                    XMP_StringPtr xmpPacket,
-                                    XMP_StringLen xmpPacketLen,
-                                    WXMP_Result * result );
-
-// =================================================================================================
-
-#if __cplusplus
-}
-#endif
-
-#endif // __WXMPFiles_hpp__
diff --git a/xmpsdk/include/client-glue/WXMPIterator.hpp b/xmpsdk/include/client-glue/WXMPIterator.hpp
deleted file mode 100644
index c5e9e26d..00000000
--- a/xmpsdk/include/client-glue/WXMPIterator.hpp
+++ /dev/null
@@ -1,83 +0,0 @@
-#if ! __WXMPIterator_hpp__
-#define __WXMPIterator_hpp__ 1
-
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "client-glue/WXMP_Common.hpp"
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// =================================================================================================
-
-#define zXMPIterator_PropCTor_1(xmpRef,schemaNS,propName,options) \
-    WXMPIterator_PropCTor_1 ( xmpRef, schemaNS, propName, options, &wResult );
-
-#define zXMPIterator_TableCTor_1(schemaNS,propName,options) \
-    WXMPIterator_TableCTor_1 ( schemaNS, propName, options, &wResult );
-    
-
-#define zXMPIterator_Next_1(schemaNS,nsSize,propPath,pathSize,propValue,valueSize,options) \
-    WXMPIterator_Next_1 ( this->iterRef, schemaNS, nsSize, propPath, pathSize, propValue, valueSize, options, &wResult );
-
-#define zXMPIterator_Skip_1(options) \
-    WXMPIterator_Skip_1 ( this->iterRef, options, &wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPIterator_PropCTor_1 ( XMPMetaRef     xmpRef,
-                          XMP_StringPtr  schemaNS,
-                          XMP_StringPtr  propName,
-                          XMP_OptionBits options,
-                          WXMP_Result *  wResult );
-
-extern void
-WXMPIterator_TableCTor_1 ( XMP_StringPtr  schemaNS,
-                           XMP_StringPtr  propName,
-                           XMP_OptionBits options,
-                           WXMP_Result *  wResult );
-
-extern void
-WXMPIterator_IncrementRefCount_1 ( XMPIteratorRef iterRef );
-
-extern void
-WXMPIterator_DecrementRefCount_1 ( XMPIteratorRef iterRef );
-
-extern void
-WXMPIterator_Unlock_1 ( XMP_OptionBits options );
-
-extern void
-WXMPIterator_Next_1 ( XMPIteratorRef   iterRef,
-                      XMP_StringPtr *  schemaNS,
-                      XMP_StringLen *  nsSize,
-                      XMP_StringPtr *  propPath,
-                      XMP_StringLen *  pathSize,
-                      XMP_StringPtr *  propValue,
-                      XMP_StringLen *  valueSize,
-                      XMP_OptionBits * options,
-                      WXMP_Result *    wResult );
-
-extern void
-WXMPIterator_Skip_1 ( XMPIteratorRef iterRef,
-                      XMP_OptionBits options,
-                      WXMP_Result *  wResult );
-
-extern void
-WXMPUtils_UnlockIter_1 ( XMPIteratorRef iterRef,
-                         XMP_OptionBits options );
-
-// =================================================================================================
-
-#if __cplusplus
-} /* extern "C" */
-#endif
-
-#endif  // __WXMPIterator_hpp__
diff --git a/xmpsdk/include/client-glue/WXMPMeta.hpp b/xmpsdk/include/client-glue/WXMPMeta.hpp
deleted file mode 100644
index ca943742..00000000
--- a/xmpsdk/include/client-glue/WXMPMeta.hpp
+++ /dev/null
@@ -1,622 +0,0 @@
-#if ! __WXMPMeta_hpp__
-#define __WXMPMeta_hpp__ 1
-
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "client-glue/WXMP_Common.hpp"
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// =================================================================================================
-#define zXMPMeta_GetVersionInfo_1(info) \
-    WXMPMeta_GetVersionInfo_1 ( info /* no wResult */ )
-
-#define zXMPMeta_Initialize_1() \
-    WXMPMeta_Initialize_1 ( &wResult )
-#define zXMPMeta_Terminate_1() \
-    WXMPMeta_Terminate_1 ( /* no wResult */ )
-
-#define zXMPMeta_CTor_1() \
-    WXMPMeta_CTor_1 ( &wResult )
-
-#define zXMPMeta_GetGlobalOptions_1() \
-    WXMPMeta_GetGlobalOptions_1 ( &wResult )
-
-#define zXMPMeta_SetGlobalOptions_1(options) \
-    WXMPMeta_SetGlobalOptions_1 ( options, &wResult )
-
-#define zXMPMeta_DumpNamespaces_1(outProc,refCon) \
-    WXMPMeta_DumpNamespaces_1 ( outProc, refCon, &wResult )
-
-#define zXMPMeta_DumpAliases_1(outProc,refCon) \
-    WXMPMeta_DumpAliases_1 ( outProc, refCon, &wResult )
-
-#define zXMPMeta_RegisterNamespace_1(namespaceURI,prefix) \
-    WXMPMeta_RegisterNamespace_1 ( namespaceURI, prefix, &wResult )
-
-#define zXMPMeta_GetNamespacePrefix_1(namespaceURI,namespacePrefix,prefixSize) \
-    WXMPMeta_GetNamespacePrefix_1 ( namespaceURI, namespacePrefix, prefixSize, &wResult )
-
-#define zXMPMeta_GetNamespaceURI_1(namespacePrefix,namespaceURI,uriSize) \
-    WXMPMeta_GetNamespaceURI_1 ( namespacePrefix, namespaceURI, uriSize, &wResult )
-
-#define zXMPMeta_DeleteNamespace_1(namespaceURI) \
-    WXMPMeta_DeleteNamespace_1 ( namespaceURI, &wResult )
-
-#define zXMPMeta_RegisterAlias_1(aliasNS,aliasProp,actualNS,actualProp,arrayForm) \
-    WXMPMeta_RegisterAlias_1 ( aliasNS, aliasProp, actualNS, actualProp, arrayForm, &wResult )
-
-#define zXMPMeta_ResolveAlias_1(aliasNS,aliasProp,actualNS,nsSize,actualProp,propSize,arrayForm) \
-    WXMPMeta_ResolveAlias_1 ( aliasNS, aliasProp, actualNS, nsSize, actualProp, propSize, arrayForm, &wResult )
-
-#define zXMPMeta_DeleteAlias_1(aliasNS,aliasProp) \
-    WXMPMeta_DeleteAlias_1 ( aliasNS, aliasProp, &wResult )
-
-#define zXMPMeta_RegisterStandardAliases_1(schemaNS) \
-    WXMPMeta_RegisterStandardAliases_1 ( schemaNS, &wResult )
-
-#define zXMPMeta_GetProperty_1(schemaNS,propName,propValue,valueSize,options) \
-    WXMPMeta_GetProperty_1 ( this->xmpRef, schemaNS, propName, propValue, valueSize, options, &wResult )
-
-#define zXMPMeta_GetArrayItem_1(schemaNS,arrayName,itemIndex,itemValue,valueSize,options) \
-    WXMPMeta_GetArrayItem_1 ( this->xmpRef, schemaNS, arrayName, itemIndex, itemValue, valueSize, options, &wResult )
-
-#define zXMPMeta_GetStructField_1(schemaNS,structName,fieldNS,fieldName,fieldValue,valueSize,options) \
-    WXMPMeta_GetStructField_1 ( this->xmpRef, schemaNS, structName, fieldNS, fieldName, fieldValue, valueSize, options, &wResult )
-
-#define zXMPMeta_GetQualifier_1(schemaNS,propName,qualNS,qualName,qualValue,valueSize,options) \
-    WXMPMeta_GetQualifier_1 ( this->xmpRef, schemaNS, propName, qualNS, qualName, qualValue, valueSize, options, &wResult )
-
-#define zXMPMeta_SetProperty_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_SetProperty_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_SetArrayItem_1(schemaNS,arrayName,itemIndex,itemValue,options) \
-    WXMPMeta_SetArrayItem_1 ( this->xmpRef, schemaNS, arrayName, itemIndex, itemValue, options, &wResult )
-
-#define zXMPMeta_AppendArrayItem_1(schemaNS,arrayName,arrayOptions,itemValue,options) \
-    WXMPMeta_AppendArrayItem_1 ( this->xmpRef, schemaNS, arrayName, arrayOptions, itemValue, options, &wResult )
-
-#define zXMPMeta_SetStructField_1(schemaNS,structName,fieldNS,fieldName,fieldValue,options) \
-    WXMPMeta_SetStructField_1 ( this->xmpRef, schemaNS, structName, fieldNS, fieldName, fieldValue, options, &wResult )
-
-#define zXMPMeta_SetQualifier_1(schemaNS,propName,qualNS,qualName,qualValue,options) \
-    WXMPMeta_SetQualifier_1 ( this->xmpRef, schemaNS, propName, qualNS, qualName, qualValue, options, &wResult )
-
-#define zXMPMeta_DeleteProperty_1(schemaNS,propName) \
-    WXMPMeta_DeleteProperty_1 ( this->xmpRef, schemaNS, propName, &wResult )
-
-#define zXMPMeta_DeleteArrayItem_1(schemaNS,arrayName,itemIndex) \
-    WXMPMeta_DeleteArrayItem_1 ( this->xmpRef, schemaNS, arrayName, itemIndex, &wResult )
-
-#define zXMPMeta_DeleteStructField_1(schemaNS,structName,fieldNS,fieldName) \
-    WXMPMeta_DeleteStructField_1 ( this->xmpRef, schemaNS, structName, fieldNS, fieldName, &wResult )
-
-#define zXMPMeta_DeleteQualifier_1(schemaNS,propName,qualNS,qualName) \
-    WXMPMeta_DeleteQualifier_1 ( this->xmpRef, schemaNS, propName, qualNS, qualName, &wResult )
-
-#define zXMPMeta_DoesPropertyExist_1(schemaNS,propName) \
-    WXMPMeta_DoesPropertyExist_1 ( this->xmpRef, schemaNS, propName, &wResult )
-
-#define zXMPMeta_DoesArrayItemExist_1(schemaNS,arrayName,itemIndex) \
-    WXMPMeta_DoesArrayItemExist_1 ( this->xmpRef, schemaNS, arrayName, itemIndex, &wResult )
-
-#define zXMPMeta_DoesStructFieldExist_1(schemaNS,structName,fieldNS,fieldName) \
-    WXMPMeta_DoesStructFieldExist_1 ( this->xmpRef, schemaNS, structName, fieldNS, fieldName, &wResult )
-
-#define zXMPMeta_DoesQualifierExist_1(schemaNS,propName,qualNS,qualName) \
-    WXMPMeta_DoesQualifierExist_1 ( this->xmpRef, schemaNS, propName, qualNS, qualName, &wResult )
-
-#define zXMPMeta_GetLocalizedText_1(schemaNS,altTextName,genericLang,specificLang,actualLang,langSize,itemValue,valueSize,options) \
-    WXMPMeta_GetLocalizedText_1 ( this->xmpRef, schemaNS, altTextName, genericLang, specificLang, actualLang, langSize, itemValue, valueSize, options, &wResult )
-
-#define zXMPMeta_SetLocalizedText_1(schemaNS,altTextName,genericLang,specificLang,itemValue,options) \
-    WXMPMeta_SetLocalizedText_1 ( this->xmpRef, schemaNS, altTextName, genericLang, specificLang, itemValue, options, &wResult )
-
-#define zXMPMeta_GetProperty_Bool_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_GetProperty_Bool_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_GetProperty_Int_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_GetProperty_Int_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_GetProperty_Int64_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_GetProperty_Int64_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_GetProperty_Float_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_GetProperty_Float_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_GetProperty_Date_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_GetProperty_Date_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_SetProperty_Bool_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_SetProperty_Bool_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_SetProperty_Int_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_SetProperty_Int_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_SetProperty_Int64_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_SetProperty_Int64_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_SetProperty_Float_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_SetProperty_Float_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_SetProperty_Date_1(schemaNS,propName,propValue,options) \
-    WXMPMeta_SetProperty_Date_1 ( this->xmpRef, schemaNS, propName, propValue, options, &wResult )
-
-#define zXMPMeta_GetObjectName_1(namePtr,nameLen) \
-    WXMPMeta_GetObjectName_1 ( this->xmpRef, namePtr, nameLen, &wResult )
-
-#define zXMPMeta_SetObjectName_1(name) \
-    WXMPMeta_SetObjectName_1 ( this->xmpRef, name, &wResult )
-
-#define zXMPMeta_GetObjectOptions_1() \
-    WXMPMeta_GetObjectOptions_1 ( this->xmpRef, &wResult )
-
-#define zXMPMeta_SetObjectOptions_1(options) \
-    WXMPMeta_SetObjectOptions_1 ( this->xmpRef, options, &wResult )
-
-#define zXMPMeta_Sort_1() \
-    WXMPMeta_Sort_1 ( this->xmpRef, &wResult )
-
-#define zXMPMeta_Erase_1() \
-    WXMPMeta_Erase_1 ( this->xmpRef, &wResult )
-
-#define zXMPMeta_Clone_1(options) \
-    WXMPMeta_Clone_1 ( this->xmpRef, options, &wResult )
-
-#define zXMPMeta_CountArrayItems_1(schemaNS,arrayName) \
-    WXMPMeta_CountArrayItems_1 ( this->xmpRef, schemaNS, arrayName, &wResult )
-
-#define zXMPMeta_DumpObject_1(outProc,refCon) \
-    WXMPMeta_DumpObject_1 ( this->xmpRef, outProc, refCon, &wResult )
-
-#define zXMPMeta_ParseFromBuffer_1(buffer,bufferSize,options) \
-    WXMPMeta_ParseFromBuffer_1 ( this->xmpRef, buffer, bufferSize, options, &wResult )
-
-#define zXMPMeta_SerializeToBuffer_1(pktString,pktSize,options,padding,newline,indent,baseIndent) \
-    WXMPMeta_SerializeToBuffer_1 ( this->xmpRef, pktString, pktSize, options, padding, newline, indent, baseIndent, &wResult )
-
-// =================================================================================================
-
-extern void
-WXMPMeta_GetVersionInfo_1 ( XMP_VersionInfo * info );
-
-extern void
-WXMPMeta_Initialize_1 ( WXMP_Result * wResult );
-extern void
-WXMPMeta_Terminate_1();
-
-extern void
-WXMPMeta_Unlock_1 ( XMP_OptionBits options );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_CTor_1 ( WXMP_Result * wResult );
-
-extern void
-WXMPMeta_IncrementRefCount_1 ( XMPMetaRef xmpRef );
-
-extern void
-WXMPMeta_DecrementRefCount_1 ( XMPMetaRef xmpRef );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_GetGlobalOptions_1 ( WXMP_Result * wResult );
-
-extern void
-WXMPMeta_SetGlobalOptions_1 ( XMP_OptionBits options,
-                              WXMP_Result *  wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_DumpNamespaces_1 ( XMP_TextOutputProc outProc,
-                            void *             refCon,
-                            WXMP_Result *      wResult );
-
-extern void
-WXMPMeta_DumpAliases_1 ( XMP_TextOutputProc outProc,
-                         void *             refCon,
-                         WXMP_Result *      wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_RegisterNamespace_1 ( XMP_StringPtr   namespaceURI,
-                               XMP_StringPtr   prefix,
-                               WXMP_Result *   wResult );
-
-extern void
-WXMPMeta_GetNamespacePrefix_1 ( XMP_StringPtr   namespaceURI,
-                                XMP_StringPtr * namespacePrefix,
-                                XMP_StringLen * prefixSize,
-                                WXMP_Result *   wResult );
-
-extern void
-WXMPMeta_GetNamespaceURI_1 ( XMP_StringPtr   namespacePrefix,
-                             XMP_StringPtr * namespaceURI,
-                             XMP_StringLen * uriSize,
-                             WXMP_Result *   wResult );
-
-extern void
-WXMPMeta_DeleteNamespace_1 ( XMP_StringPtr namespaceURI,
-                             WXMP_Result * wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_RegisterAlias_1 ( XMP_StringPtr  aliasNS,
-                           XMP_StringPtr  aliasProp,
-                           XMP_StringPtr  actualNS,
-                           XMP_StringPtr  actualProp,
-                           XMP_OptionBits arrayForm,
-                           WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_ResolveAlias_1 ( XMP_StringPtr    aliasNS,
-                          XMP_StringPtr    aliasProp,
-                          XMP_StringPtr *  actualNS,
-                          XMP_StringLen *  nsSize,
-                          XMP_StringPtr *  actualProp,
-                          XMP_StringLen *  propSize,
-                          XMP_OptionBits * arrayForm,
-                          WXMP_Result *    wResult );
-
-extern void
-WXMPMeta_DeleteAlias_1 ( XMP_StringPtr aliasNS,
-                         XMP_StringPtr aliasProp,
-                         WXMP_Result * wResult );
-
-extern void
-WXMPMeta_RegisterStandardAliases_1 ( XMP_StringPtr schemaNS,
-                                     WXMP_Result * wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_UnlockObject_1 ( XMPMetaRef     xmpRef,
-                          XMP_OptionBits options );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_GetProperty_1 ( XMPMetaRef       xmpRef,
-                         XMP_StringPtr    schemaNS,
-                         XMP_StringPtr    propName,
-                         XMP_StringPtr *  propValue,
-                         XMP_StringLen *  valueSize,
-                         XMP_OptionBits * options,
-                         WXMP_Result *    wResult ) /* const */ ;
-
-extern void
-WXMPMeta_GetArrayItem_1 ( XMPMetaRef       xmpRef,
-                          XMP_StringPtr    schemaNS,
-                          XMP_StringPtr    arrayName,
-                          XMP_Index        itemIndex,
-                          XMP_StringPtr *  itemValue,
-                          XMP_StringLen *  valueSize,
-                          XMP_OptionBits * options,
-                          WXMP_Result *    wResult ) /* const */ ;
-
-extern void
-WXMPMeta_GetStructField_1 ( XMPMetaRef       xmpRef,
-                            XMP_StringPtr    schemaNS,
-                            XMP_StringPtr    structName,
-                            XMP_StringPtr    fieldNS,
-                            XMP_StringPtr    fieldName,
-                            XMP_StringPtr *  fieldValue,
-                            XMP_StringLen *  valueSize,
-                            XMP_OptionBits * options,
-                            WXMP_Result *    wResult ) /* const */ ;
-
-extern void
-WXMPMeta_GetQualifier_1 ( XMPMetaRef       xmpRef,
-                          XMP_StringPtr    schemaNS,
-                          XMP_StringPtr    propName,
-                          XMP_StringPtr    qualNS,
-                          XMP_StringPtr    qualName,
-                          XMP_StringPtr *  qualValue,
-                          XMP_StringLen *  valueSize,
-                          XMP_OptionBits * options,
-                          WXMP_Result *    wResult ) /* const */ ;
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_SetProperty_1 ( XMPMetaRef     xmpRef,
-                         XMP_StringPtr  schemaNS,
-                         XMP_StringPtr  propName,
-                         XMP_StringPtr  propValue,
-                         XMP_OptionBits options,
-                         WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_SetArrayItem_1 ( XMPMetaRef     xmpRef,
-                          XMP_StringPtr  schemaNS,
-                          XMP_StringPtr  arrayName,
-                          XMP_Index      itemIndex,
-                          XMP_StringPtr  itemValue,
-                          XMP_OptionBits options,
-                          WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_AppendArrayItem_1 ( XMPMetaRef     xmpRef,
-                             XMP_StringPtr  schemaNS,
-                             XMP_StringPtr  arrayName,
-                             XMP_OptionBits arrayOptions,
-                             XMP_StringPtr  itemValue,
-                             XMP_OptionBits options,
-                             WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_SetStructField_1 ( XMPMetaRef     xmpRef,
-                            XMP_StringPtr  schemaNS,
-                            XMP_StringPtr  structName,
-                            XMP_StringPtr  fieldNS,
-                            XMP_StringPtr  fieldName,
-                            XMP_StringPtr  fieldValue,
-                            XMP_OptionBits options,
-                            WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_SetQualifier_1 ( XMPMetaRef     xmpRef,
-                          XMP_StringPtr  schemaNS,
-                          XMP_StringPtr  propName,
-                          XMP_StringPtr  qualNS,
-                          XMP_StringPtr  qualName,
-                          XMP_StringPtr  qualValue,
-                          XMP_OptionBits options,
-                          WXMP_Result *  wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_DeleteProperty_1 ( XMPMetaRef    xmpRef,
-                            XMP_StringPtr schemaNS,
-                            XMP_StringPtr propName,
-                            WXMP_Result * wResult );
-
-extern void
-WXMPMeta_DeleteArrayItem_1 ( XMPMetaRef    xmpRef,
-                             XMP_StringPtr schemaNS,
-                             XMP_StringPtr arrayName,
-                             XMP_Index     itemIndex,
-                             WXMP_Result * wResult );
-
-extern void
-WXMPMeta_DeleteStructField_1 ( XMPMetaRef    xmpRef,
-                               XMP_StringPtr schemaNS,
-                               XMP_StringPtr structName,
-                               XMP_StringPtr fieldNS,
-                               XMP_StringPtr fieldName,
-                               WXMP_Result * wResult );
-
-extern void
-WXMPMeta_DeleteQualifier_1 ( XMPMetaRef    xmpRef,
-                             XMP_StringPtr schemaNS,
-                             XMP_StringPtr propName,
-                             XMP_StringPtr qualNS,
-                             XMP_StringPtr qualName,
-                             WXMP_Result * wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_DoesPropertyExist_1 ( XMPMetaRef    xmpRef,
-                               XMP_StringPtr schemaNS,
-                               XMP_StringPtr propName,
-                               WXMP_Result * wResult ) /* const */ ;
-
-extern void
-WXMPMeta_DoesArrayItemExist_1 ( XMPMetaRef    xmpRef,
-                                XMP_StringPtr schemaNS,
-                                XMP_StringPtr arrayName,
-                                XMP_Index     itemIndex,
-                                WXMP_Result * wResult ) /* const */ ;
-
-extern void
-WXMPMeta_DoesStructFieldExist_1 ( XMPMetaRef    xmpRef,
-                                  XMP_StringPtr schemaNS,
-                                  XMP_StringPtr structName,
-                                  XMP_StringPtr fieldNS,
-                                  XMP_StringPtr fieldName,
-                                  WXMP_Result * wResult ) /* const */ ;
-
-extern void
-WXMPMeta_DoesQualifierExist_1 ( XMPMetaRef    xmpRef,
-                                XMP_StringPtr schemaNS,
-                                XMP_StringPtr propName,
-                                XMP_StringPtr qualNS,
-                                XMP_StringPtr qualName,
-                                WXMP_Result * wResult ) /* const */ ;
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_GetLocalizedText_1 ( XMPMetaRef       xmpRef,
-                              XMP_StringPtr    schemaNS,
-                              XMP_StringPtr    altTextName,
-                              XMP_StringPtr    genericLang,
-                              XMP_StringPtr    specificLang,
-                              XMP_StringPtr *  actualLang,
-                              XMP_StringLen *  langSize,
-                              XMP_StringPtr *  itemValue,
-                              XMP_StringLen *  valueSize,
-                              XMP_OptionBits * options,
-                              WXMP_Result *    wResult ) /* const */ ;
-
-extern void
-WXMPMeta_SetLocalizedText_1 ( XMPMetaRef     xmpRef,
-                              XMP_StringPtr  schemaNS,
-                              XMP_StringPtr  altTextName,
-                              XMP_StringPtr  genericLang,
-                              XMP_StringPtr  specificLang,
-                              XMP_StringPtr  itemValue,
-                              XMP_OptionBits options,
-                              WXMP_Result *  wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_GetProperty_Bool_1 ( XMPMetaRef       xmpRef,
-                              XMP_StringPtr    schemaNS,
-                              XMP_StringPtr    propName,
-                              XMP_Bool *       propValue,
-                              XMP_OptionBits * options,
-                              WXMP_Result *    wResult ) /* const */ ;
-
-extern void
-WXMPMeta_GetProperty_Int_1 ( XMPMetaRef       xmpRef,
-                             XMP_StringPtr    schemaNS,
-                             XMP_StringPtr    propName,
-                             XMP_Int32 *      propValue,
-                             XMP_OptionBits * options,
-                             WXMP_Result *    wResult ) /* const */ ;
-
-extern void
-WXMPMeta_GetProperty_Int64_1 ( XMPMetaRef       xmpRef,
-                               XMP_StringPtr    schemaNS,
-                               XMP_StringPtr    propName,
-                               XMP_Int64 *      propValue,
-                               XMP_OptionBits * options,
-                               WXMP_Result *    wResult ) /* const */ ;
-
-extern void
-WXMPMeta_GetProperty_Float_1 ( XMPMetaRef       xmpRef,
-                               XMP_StringPtr    schemaNS,
-                               XMP_StringPtr    propName,
-                               double *         propValue,
-                               XMP_OptionBits * options,
-                               WXMP_Result *    wResult ) /* const */ ;
-
-extern void
-WXMPMeta_GetProperty_Date_1 ( XMPMetaRef       xmpRef,
-                              XMP_StringPtr    schemaNS,
-                              XMP_StringPtr    propName,
-                              XMP_DateTime *   propValue,
-                              XMP_OptionBits * options,
-                              WXMP_Result *    wResult ) /* const */ ;
-
-extern void
-WXMPMeta_SetProperty_Bool_1 ( XMPMetaRef     xmpRef,
-                              XMP_StringPtr  schemaNS,
-                              XMP_StringPtr  propName,
-                              XMP_Bool       propValue,
-                              XMP_OptionBits options,
-                              WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_SetProperty_Int_1 ( XMPMetaRef     xmpRef,
-                             XMP_StringPtr  schemaNS,
-                             XMP_StringPtr  propName,
-                             XMP_Int32      propValue,
-                             XMP_OptionBits options,
-                             WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_SetProperty_Int64_1 ( XMPMetaRef     xmpRef,
-                               XMP_StringPtr  schemaNS,
-                               XMP_StringPtr  propName,
-                               XMP_Int64      propValue,
-                               XMP_OptionBits options,
-                               WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_SetProperty_Float_1 ( XMPMetaRef     xmpRef,
-                               XMP_StringPtr  schemaNS,
-                               XMP_StringPtr  propName,
-                               double         propValue,
-                               XMP_OptionBits options,
-                               WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_SetProperty_Date_1 ( XMPMetaRef           xmpRef,
-                              XMP_StringPtr        schemaNS,
-                              XMP_StringPtr        propName,
-                              const XMP_DateTime & propValue,
-                              XMP_OptionBits       options,
-                              WXMP_Result *        wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_GetObjectName_1 ( XMPMetaRef      xmpRef,
-                           XMP_StringPtr * namePtr,
-                           XMP_StringLen * nameLen,
-                           WXMP_Result *   wResult ) /* const */ ;
-
-extern void
-WXMPMeta_SetObjectName_1 ( XMPMetaRef    xmpRef,
-                           XMP_StringPtr name,
-                           WXMP_Result * wResult );
-
-extern void
-WXMPMeta_GetObjectOptions_1 ( XMPMetaRef    xmpRef,
-                              WXMP_Result * wResult ) /* const */ ;
-
-extern void
-WXMPMeta_SetObjectOptions_1 ( XMPMetaRef     xmpRef,
-                              XMP_OptionBits options,
-                              WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_Sort_1 ( XMPMetaRef    xmpRef,
-                  WXMP_Result * wResult );
-
-extern void
-WXMPMeta_Erase_1 ( XMPMetaRef    xmpRef,
-                   WXMP_Result * wResult );
-
-extern void
-WXMPMeta_Clone_1 ( XMPMetaRef     xmpRef,
-                   XMP_OptionBits options,
-                   WXMP_Result *  wResult ) /* const */ ;
-
-extern void
-WXMPMeta_CountArrayItems_1 ( XMPMetaRef    xmpRef,
-                             XMP_StringPtr schemaNS,
-                             XMP_StringPtr arrayName,
-                             WXMP_Result * wResult ) /* const */ ;
-
-extern void
-WXMPMeta_DumpObject_1 ( XMPMetaRef         xmpRef,
-                        XMP_TextOutputProc outProc,
-                        void *             refCon,
-                        WXMP_Result *      wResult ) /* const */ ;
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPMeta_ParseFromBuffer_1 ( XMPMetaRef     xmpRef,
-                             XMP_StringPtr  buffer,
-                             XMP_StringLen  bufferSize,
-                             XMP_OptionBits options,
-                             WXMP_Result *  wResult );
-
-extern void
-WXMPMeta_SerializeToBuffer_1 ( XMPMetaRef      xmpRef,
-                               XMP_StringPtr * pktString,
-                               XMP_StringLen * pktSize,
-                               XMP_OptionBits  options,
-                               XMP_StringLen   padding,
-                               XMP_StringPtr   newline,
-                               XMP_StringPtr   indent,
-                               XMP_Index       baseIndent,
-                               WXMP_Result *   wResult ) /* const */ ;
-
-// =================================================================================================
-
-#if __cplusplus
-} /* extern "C" */
-#endif
-
-#endif  // __WXMPMeta_hpp__
diff --git a/xmpsdk/include/client-glue/WXMPUtils.hpp b/xmpsdk/include/client-glue/WXMPUtils.hpp
deleted file mode 100644
index 55890fc5..00000000
--- a/xmpsdk/include/client-glue/WXMPUtils.hpp
+++ /dev/null
@@ -1,322 +0,0 @@
-#if ! __WXMPUtils_hpp__
-#define __WXMPUtils_hpp__ 1
-
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "client-glue/WXMP_Common.hpp"
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// =================================================================================================
-
-#define zXMPUtils_ComposeArrayItemPath_1(schemaNS,arrayName,itemIndex,fullPath,pathSize) \
-    WXMPUtils_ComposeArrayItemPath_1 ( schemaNS, arrayName, itemIndex, fullPath, pathSize, &wResult );
-
-#define zXMPUtils_ComposeStructFieldPath_1(schemaNS,structName,fieldNS,fieldName,fullPath,pathSize) \
-    WXMPUtils_ComposeStructFieldPath_1 ( schemaNS, structName, fieldNS, fieldName, fullPath, pathSize, &wResult );
-
-#define zXMPUtils_ComposeQualifierPath_1(schemaNS,propName,qualNS,qualName,fullPath,pathSize) \
-    WXMPUtils_ComposeQualifierPath_1 ( schemaNS, propName, qualNS, qualName, fullPath, pathSize, &wResult );
-
-#define zXMPUtils_ComposeLangSelector_1(schemaNS,arrayName,langName,fullPath,pathSize) \
-    WXMPUtils_ComposeLangSelector_1 ( schemaNS, arrayName, langName, fullPath, pathSize, &wResult );
-
-#define zXMPUtils_ComposeFieldSelector_1(schemaNS,arrayName,fieldNS,fieldName,fieldValue,fullPath,pathSize) \
-    WXMPUtils_ComposeFieldSelector_1 ( schemaNS, arrayName, fieldNS, fieldName, fieldValue, fullPath, pathSize, &wResult );
-
-#define zXMPUtils_ConvertFromBool_1(binValue,strValue,strSize) \
-    WXMPUtils_ConvertFromBool_1 ( binValue, strValue, strSize, &wResult );
-
-#define zXMPUtils_ConvertFromInt_1(binValue,format,strValue,strSize) \
-    WXMPUtils_ConvertFromInt_1 ( binValue, format, strValue, strSize, &wResult );
-
-#define zXMPUtils_ConvertFromInt64_1(binValue,format,strValue,strSize) \
-    WXMPUtils_ConvertFromInt64_1 ( binValue, format, strValue, strSize, &wResult );
-
-#define zXMPUtils_ConvertFromFloat_1(binValue,format,strValue,strSize) \
-    WXMPUtils_ConvertFromFloat_1 ( binValue, format, strValue, strSize, &wResult );
-
-#define zXMPUtils_ConvertFromDate_1(binValue,strValue,strSize) \
-    WXMPUtils_ConvertFromDate_1 ( binValue, strValue, strSize, &wResult );
-
-#define zXMPUtils_ConvertToBool_1(strValue) \
-    WXMPUtils_ConvertToBool_1 ( strValue, &wResult );
-
-#define zXMPUtils_ConvertToInt_1(strValue) \
-    WXMPUtils_ConvertToInt_1 ( strValue, &wResult );
-
-#define zXMPUtils_ConvertToInt64_1(strValue) \
-    WXMPUtils_ConvertToInt64_1 ( strValue, &wResult );
-
-#define zXMPUtils_ConvertToFloat_1(strValue) \
-    WXMPUtils_ConvertToFloat_1 ( strValue, &wResult );
-
-#define zXMPUtils_ConvertToDate_1(strValue,binValue) \
-    WXMPUtils_ConvertToDate_1 ( strValue, binValue, &wResult );
-
-#define zXMPUtils_CurrentDateTime_1(time) \
-    WXMPUtils_CurrentDateTime_1 ( time, &wResult );
-
-#define zXMPUtils_SetTimeZone_1(time) \
-    WXMPUtils_SetTimeZone_1 ( time, &wResult );
-
-#define zXMPUtils_ConvertToUTCTime_1(time) \
-    WXMPUtils_ConvertToUTCTime_1 ( time, &wResult );
-
-#define zXMPUtils_ConvertToLocalTime_1(time) \
-    WXMPUtils_ConvertToLocalTime_1 ( time, &wResult );
-
-#define zXMPUtils_CompareDateTime_1(left,right) \
-    WXMPUtils_CompareDateTime_1 ( left, right, &wResult );
-
-#define zXMPUtils_EncodeToBase64_1(rawStr,rawLen,encodedStr,encodedLen) \
-    WXMPUtils_EncodeToBase64_1 ( rawStr, rawLen, encodedStr, encodedLen, &wResult );
-
-#define zXMPUtils_DecodeFromBase64_1(encodedStr,encodedLen,rawStr,rawLen) \
-    WXMPUtils_DecodeFromBase64_1 ( encodedStr, encodedLen, rawStr, rawLen, &wResult );
-
-#define zXMPUtils_PackageForJPEG_1(xmpObj,stdStr,stdLen,extStr,extLen,digestStr,digestLen) \
-    WXMPUtils_PackageForJPEG_1 ( xmpObj, stdStr, stdLen, extStr, extLen, digestStr, digestLen, &wResult );
-
-#define zXMPUtils_MergeFromJPEG_1(fullXMP,extendedXMP) \
-    WXMPUtils_MergeFromJPEG_1 ( fullXMP, extendedXMP, &wResult );
-
-#define zXMPUtils_CatenateArrayItems_1(xmpObj,schemaNS,arrayName,separator,quotes,options,catedPtr,catedLen) \
-    WXMPUtils_CatenateArrayItems_1 ( xmpObj, schemaNS, arrayName, separator, quotes, options, catedPtr, catedLen, &wResult );
-
-#define zXMPUtils_SeparateArrayItems_1(xmpObj,schemaNS,arrayName,options,catedStr) \
-    WXMPUtils_SeparateArrayItems_1 ( xmpObj, schemaNS, arrayName, options, catedStr, &wResult );
-
-#define zXMPUtils_RemoveProperties_1(xmpObj,schemaNS,propName,options) \
-    WXMPUtils_RemoveProperties_1 ( xmpObj, schemaNS, propName, options, &wResult );
-
-#define zXMPUtils_AppendProperties_1(source,dest,options) \
-    WXMPUtils_AppendProperties_1 ( source, dest, options, &wResult );
-
-#define zXMPUtils_DuplicateSubtree_1(source,dest,sourceNS,sourceRoot,destNS,destRoot,options) \
-    WXMPUtils_DuplicateSubtree_1 ( source, dest, sourceNS, sourceRoot, destNS, destRoot, options, &wResult );
-
-// =================================================================================================
-
-extern void
-WXMPUtils_Unlock_1 ( XMP_OptionBits options );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPUtils_ComposeArrayItemPath_1 ( XMP_StringPtr   schemaNS,
-                                   XMP_StringPtr   arrayName,
-                                   XMP_Index       itemIndex,
-                                   XMP_StringPtr * fullPath,
-                                   XMP_StringLen * pathSize,
-                                   WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_ComposeStructFieldPath_1 ( XMP_StringPtr   schemaNS,
-                                     XMP_StringPtr   structName,
-                                     XMP_StringPtr   fieldNS,
-                                     XMP_StringPtr   fieldName,
-                                     XMP_StringPtr * fullPath,
-                                     XMP_StringLen * pathSize,
-                                     WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_ComposeQualifierPath_1 ( XMP_StringPtr   schemaNS,
-                                   XMP_StringPtr   propName,
-                                   XMP_StringPtr   qualNS,
-                                   XMP_StringPtr   qualName,
-                                   XMP_StringPtr * fullPath,
-                                   XMP_StringLen * pathSize,
-                                   WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_ComposeLangSelector_1 ( XMP_StringPtr   schemaNS,
-                                  XMP_StringPtr   arrayName,
-                                  XMP_StringPtr   langName,
-                                  XMP_StringPtr * fullPath,
-                                  XMP_StringLen * pathSize,
-                                  WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_ComposeFieldSelector_1 ( XMP_StringPtr   schemaNS,
-                                   XMP_StringPtr   arrayName,
-                                   XMP_StringPtr   fieldNS,
-                                   XMP_StringPtr   fieldName,
-                                   XMP_StringPtr   fieldValue,
-                                   XMP_StringPtr * fullPath,
-                                   XMP_StringLen * pathSize,
-                                   WXMP_Result *   wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPUtils_ConvertFromBool_1 ( XMP_Bool        binValue,
-                              XMP_StringPtr * strValue,
-                              XMP_StringLen * strSize,
-                              WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_ConvertFromInt_1 ( XMP_Int32       binValue,
-                             XMP_StringPtr   format,
-                             XMP_StringPtr * strValue,
-                             XMP_StringLen * strSize,
-                             WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_ConvertFromInt64_1 ( XMP_Int64       binValue,
-                               XMP_StringPtr   format,
-                               XMP_StringPtr * strValue,
-                               XMP_StringLen * strSize,
-                               WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_ConvertFromFloat_1 ( double          binValue,
-                               XMP_StringPtr   format,
-                               XMP_StringPtr * strValue,
-                               XMP_StringLen * strSize,
-                               WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_ConvertFromDate_1 ( const XMP_DateTime & binValue,
-                              XMP_StringPtr *      strValue,
-                              XMP_StringLen *      strSize,
-                              WXMP_Result *        wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPUtils_ConvertToBool_1 ( XMP_StringPtr strValue,
-                            WXMP_Result * wResult );
-
-extern void
-WXMPUtils_ConvertToInt_1 ( XMP_StringPtr strValue,
-                           WXMP_Result * wResult );
-
-extern void
-WXMPUtils_ConvertToInt64_1 ( XMP_StringPtr strValue,
-                             WXMP_Result * wResult );
-
-extern void
-WXMPUtils_ConvertToFloat_1 ( XMP_StringPtr strValue,
-                             WXMP_Result * wResult );
-
-extern void
-WXMPUtils_ConvertToDate_1 ( XMP_StringPtr  strValue,
-                            XMP_DateTime * binValue,
-                            WXMP_Result *  wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPUtils_CurrentDateTime_1 ( XMP_DateTime * time,
-                              WXMP_Result *  wResult );
-
-extern void
-WXMPUtils_SetTimeZone_1 ( XMP_DateTime * time,
-                          WXMP_Result *  wResult );
-
-extern void
-WXMPUtils_ConvertToUTCTime_1 ( XMP_DateTime * time,
-                               WXMP_Result *  wResult );
-
-extern void
-WXMPUtils_ConvertToLocalTime_1 ( XMP_DateTime * time,
-                                 WXMP_Result *  wResult );
-
-extern void
-WXMPUtils_CompareDateTime_1 ( const XMP_DateTime & left,
-                              const XMP_DateTime & right,
-                              WXMP_Result *        wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPUtils_EncodeToBase64_1 ( XMP_StringPtr   rawStr,
-                             XMP_StringLen   rawLen,
-                             XMP_StringPtr * encodedStr,
-                             XMP_StringLen * encodedLen,
-                             WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_DecodeFromBase64_1 ( XMP_StringPtr   encodedStr,
-                               XMP_StringLen   encodedLen,
-                               XMP_StringPtr * rawStr,
-                               XMP_StringLen * rawLen,
-                               WXMP_Result *   wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPUtils_PackageForJPEG_1 ( XMPMetaRef      xmpObj,
-                             XMP_StringPtr * stdStr,
-                             XMP_StringLen * stdLen,
-                             XMP_StringPtr * extStr,
-                             XMP_StringLen * extLen,
-                             XMP_StringPtr * digestStr,
-                             XMP_StringLen * digestLen,
-                             WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_MergeFromJPEG_1 ( XMPMetaRef    fullXMP,
-                            XMPMetaRef    extendedXMP,
-                            WXMP_Result * wResult );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void
-WXMPUtils_CatenateArrayItems_1 ( XMPMetaRef      xmpObj,
-                                 XMP_StringPtr   schemaNS,
-                                 XMP_StringPtr   arrayName,
-                                 XMP_StringPtr   separator,
-                                 XMP_StringPtr   quotes,
-                                 XMP_OptionBits  options,
-                                 XMP_StringPtr * catedStr,
-                                 XMP_StringLen * catedLen,
-                                 WXMP_Result *   wResult );
-
-extern void
-WXMPUtils_SeparateArrayItems_1 ( XMPMetaRef     xmpObj,
-                                 XMP_StringPtr  schemaNS,
-                                 XMP_StringPtr  arrayName,
-                                 XMP_OptionBits options,
-                                 XMP_StringPtr  catedStr,
-                                 WXMP_Result *  wResult );
-
-extern void
-WXMPUtils_RemoveProperties_1 ( XMPMetaRef     xmpObj,
-                               XMP_StringPtr  schemaNS,
-                               XMP_StringPtr  propName,
-                               XMP_OptionBits options,
-                               WXMP_Result *  wResult );
-
-extern void
-WXMPUtils_AppendProperties_1 ( XMPMetaRef     source,
-                               XMPMetaRef     dest,
-                               XMP_OptionBits options,
-                               WXMP_Result *  wResult );
-
-extern void
-WXMPUtils_DuplicateSubtree_1 ( XMPMetaRef     source,
-                               XMPMetaRef     dest,
-                               XMP_StringPtr  sourceNS,
-                               XMP_StringPtr  sourceRoot,
-                               XMP_StringPtr  destNS,
-                               XMP_StringPtr  destRoot,
-                               XMP_OptionBits options,
-                               WXMP_Result *  wResult );
-
-// =================================================================================================
-
-#if __cplusplus
-} /* extern "C" */
-#endif
-
-#endif  // __WXMPUtils_hpp__
diff --git a/xmpsdk/include/client-glue/WXMP_Common.hpp b/xmpsdk/include/client-glue/WXMP_Common.hpp
deleted file mode 100644
index 4d6eaab4..00000000
--- a/xmpsdk/include/client-glue/WXMP_Common.hpp
+++ /dev/null
@@ -1,123 +0,0 @@
-#if ! __WXMP_Common_hpp__
-#define __WXMP_Common_hpp__ 1
-
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#ifndef XMP_Inline
-	#if TXMP_EXPAND_INLINE
-		#define XMP_Inline inline
-	#else
-		#define XMP_Inline /* not inline */
-	#endif
-#endif
-
-#define XMP_CTorDTorIntro(Class) template <class tStringObj> XMP_Inline Class<tStringObj>
-#define XMP_MethodIntro(Class,ResultType) template <class tStringObj> XMP_Inline ResultType Class<tStringObj>
-
-struct WXMP_Result {
-    XMP_StringPtr errMessage;
-    void *        ptrResult;
-    double        floatResult;
-    XMP_Uns64     int64Result;
-    XMP_Uns32     int32Result;
-    WXMP_Result() : errMessage(0) {};
-};
-
-#if __cplusplus
-extern "C" {
-#endif
-
-#define PropagateException(res)	\
-	if ( res.errMessage != 0 ) throw XMP_Error ( res.int32Result, res.errMessage );
-
-#ifndef TraceXMPCalls
-	#define TraceXMPCalls	0
-#endif
-
-#if ! TraceXMPCalls
-	#define InvokeCheck(WCallProto) \
-    	WXMP_Result wResult;        \
-		WCallProto;                 \
-		PropagateException ( wResult )
-#else
-	#define InvokeCheck(WCallProto)                                                              \
-    	WXMP_Result wResult;                                                                     \
-    	fprintf ( stderr, "WXMP calling: %s\n", #WCallProto ); fflush ( stderr );                \
-    	WCallProto;                                                                              \
-    	if ( wResult.errMessage == 0 ) {                                                         \
-			fprintf ( stderr, "WXMP back, no error\n" ); fflush ( stderr );                      \
-    	} else {                                                                                 \
-			fprintf ( stderr, "WXMP back, error: %s\n", wResult.errMessage ); fflush ( stderr ); \
-    	}                                                                                        \
-		PropagateException ( wResult )
-#endif
-
-// -------------------------------------------------------------------------------------------------
-
-#define WrapNoCheckVoid(WCallProto) \
-	WCallProto;
-
-#define WrapCheckVoid(WCallProto) \
-    InvokeCheck(WCallProto)
-
-#define WrapCheckMetaRef(result,WCallProto) \
-    InvokeCheck(WCallProto);                \
-    XMPMetaRef result = XMPMetaRef(wResult.ptrResult)
-
-#define WrapCheckIterRef(result,WCallProto) \
-    InvokeCheck(WCallProto);                \
-    XMPIteratorRef result = XMPIteratorRef(wResult.ptrResult)
-
-#define WrapCheckDocOpsRef(result,WCallProto) \
-    InvokeCheck(WCallProto);                  \
-    XMPDocOpsRef result = XMPDocOpsRef(wResult.ptrResult)
-
-#define WrapCheckBool(result,WCallProto) \
-    InvokeCheck(WCallProto);             \
-    bool result = bool(wResult.int32Result)
-
-#define WrapCheckTriState(result,WCallProto) \
-    InvokeCheck(WCallProto);                 \
-    XMP_TriState result = XMP_TriState(wResult.int32Result)
-
-#define WrapCheckOptions(result,WCallProto) \
-    InvokeCheck(WCallProto);                \
-    XMP_OptionBits result = XMP_OptionBits(wResult.int32Result)
-
-#define WrapCheckStatus(result,WCallProto) \
-    InvokeCheck(WCallProto);               \
-    XMP_Status result = XMP_Status(wResult.int32Result)
-
-#define WrapCheckIndex(result,WCallProto) \
-    InvokeCheck(WCallProto);              \
-    XMP_Index result = XMP_Index(wResult.int32Result)
-
-#define WrapCheckInt32(result,WCallProto) \
-    InvokeCheck(WCallProto);              \
-    XMP_Int32 result = wResult.int32Result
-
-#define WrapCheckInt64(result,WCallProto) \
-    InvokeCheck(WCallProto);              \
-    XMP_Int64 result = wResult.int64Result
-
-#define WrapCheckFloat(result,WCallProto) \
-    InvokeCheck(WCallProto);              \
-    double result = wResult.floatResult
-
-#define WrapCheckFormat(result,WCallProto) \
-    InvokeCheck(WCallProto);               \
-    XMP_FileFormat result = wResult.int32Result
-
-// =================================================================================================
-
-#if __cplusplus
-} /* extern "C" */
-#endif
-
-#endif  // __WXMP_Common_hpp__
diff --git a/xmpsdk/ren-lnx.sh b/xmpsdk/ren-lnx.sh
new file mode 100755
index 00000000..32f90372
--- /dev/null
+++ b/xmpsdk/ren-lnx.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+mv staticXMPCore.ar libXMPCore.a
+mv staticXMPFiles.ar libXMPFiles.a
\ No newline at end of file
diff --git a/xmpsdk/ren-mac.sh b/xmpsdk/ren-mac.sh
new file mode 100755
index 00000000..a5b0b2fb
--- /dev/null
+++ b/xmpsdk/ren-mac.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+
+mv libXMPCoreStatic.a libXMPCore.a
+mv libXMPFilesStatic.a libXMPFiles.a
\ No newline at end of file
diff --git a/xmpsdk/ren-win.bat b/xmpsdk/ren-win.bat
new file mode 100644
index 00000000..e2c0e7f3
--- /dev/null
+++ b/xmpsdk/ren-win.bat
@@ -0,0 +1,2 @@
+ren XMPCoreStatic.lib libXMPCore.lib
+ren XMPFilesStatic.lib libXMPFiles.lib
diff --git a/xmpsdk/src/ExpatAdapter.cpp b/xmpsdk/src/ExpatAdapter.cpp
deleted file mode 100644
index 79669f52..00000000
--- a/xmpsdk/src/ExpatAdapter.cpp
+++ /dev/null
@@ -1,504 +0,0 @@
-// =================================================================================================
-// Copyright 2005-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! Must be the first #include!
-#include "XMPCore_Impl.hpp"
-
-#include "ExpatAdapter.hpp"
-#include "XMPMeta.hpp"
-
-#include "expat.h"
-
-#include <string.h>
-
-using namespace std;
-
-#if XMP_WinBuild
-#   ifdef _MSC_VER
-        #pragma warning ( disable : 4996 )	// '...' was declared deprecated
-#   endif
-#endif
-
-// *** Set memory handlers.
-
-#ifndef DumpXMLParseEvents
-	#define DumpXMLParseEvents	0
-#endif
-
-#define FullNameSeparator	'@'
-
-// =================================================================================================
-
-static void StartNamespaceDeclHandler    ( void * userData, XMP_StringPtr prefix, XMP_StringPtr uri );
-static void EndNamespaceDeclHandler      ( void * userData, XMP_StringPtr prefix );
-
-static void StartElementHandler          ( void * userData, XMP_StringPtr name, XMP_StringPtr* attrs );
-static void EndElementHandler            ( void * userData, XMP_StringPtr name );
-
-static void CharacterDataHandler         ( void * userData, XMP_StringPtr cData, int len );
-static void StartCdataSectionHandler     ( void * userData );
-static void EndCdataSectionHandler       ( void * userData );
-
-static void ProcessingInstructionHandler ( void * userData, XMP_StringPtr target, XMP_StringPtr data );
-static void CommentHandler               ( void * userData, XMP_StringPtr comment );
-
-#if BanAllEntityUsage
-
-	// For now we do this by banning DOCTYPE entirely. This is easy and consistent with what is
-	// available in recent Java XML parsers. Another, somewhat less drastic, approach would be to 
-	// ban all entity declarations. We can't allow declarations and ban references, Expat does not
-	// call the SkippedEntityHandler for references in attribute values.
-	
-	// ! Standard entities (&amp;, &lt;, &gt;, &quot;, &apos;, and numeric character references) are
-	// ! not banned. Expat handles them transparently no matter what.
-
-	static void StartDoctypeDeclHandler ( void * userData, XMP_StringPtr doctypeName,
-										  XMP_StringPtr sysid, XMP_StringPtr pubid, int has_internal_subset );
-
-#endif
-
-// =================================================================================================
-
-extern "C" ExpatAdapter * XMP_NewExpatAdapter()
-{
-	return new ExpatAdapter;
-}	// XMP_NewExpatAdapter
-
-// =================================================================================================
-
-ExpatAdapter::ExpatAdapter() : parser(0)
-{
-
-	#if XMP_DebugBuild
-		this->elemNesting = 0;
-		#if DumpXMLParseEvents
-			if ( this->parseLog == 0 ) this->parseLog = stdout;
-		#endif
-	#endif
-
-	this->parser = XML_ParserCreateNS ( 0, FullNameSeparator );
-	if ( this->parser == 0 ) XMP_Throw ( "Failure creating Expat parser", kXMPErr_ExternalFailure );
-	
-	XML_SetUserData ( this->parser, this );
-	
-	XML_SetNamespaceDeclHandler ( this->parser, StartNamespaceDeclHandler, EndNamespaceDeclHandler );
-	XML_SetElementHandler ( this->parser, StartElementHandler, EndElementHandler );
-
-	XML_SetCharacterDataHandler ( this->parser, CharacterDataHandler );
-	XML_SetCdataSectionHandler ( this->parser, StartCdataSectionHandler, EndCdataSectionHandler );
-
-	XML_SetProcessingInstructionHandler ( this->parser, ProcessingInstructionHandler );
-	XML_SetCommentHandler ( this->parser, CommentHandler );
-
-	#if BanAllEntityUsage
-		XML_SetStartDoctypeDeclHandler ( this->parser, StartDoctypeDeclHandler );
-		isAborted = false;
-	#endif
-
-	this->parseStack.push_back ( &this->tree );	// Push the XML root node.
-
-}	// ExpatAdapter::ExpatAdapter
-
-// =================================================================================================
-
-ExpatAdapter::~ExpatAdapter()
-{
-
-	if ( this->parser != 0 ) XML_ParserFree ( this->parser );
-	this->parser = 0;
-
-}	// ExpatAdapter::~ExpatAdapter
-
-// =================================================================================================
-
-#if XMP_DebugBuild
-	static XMP_VarString sExpatMessage;
-#endif
-
-static const char * kOneSpace = " ";
-
-void ExpatAdapter::ParseBuffer ( const void * buffer, size_t length, bool last /* = true */ )
-{
-	enum XML_Status status;
-	
-	if ( length == 0 ) {	// Expat does not like empty buffers.
-		if ( ! last ) return;
-		buffer = kOneSpace;
-		length = 1;
-	}
-	
-	status = XML_Parse ( this->parser, (const char *)buffer, length, last );
-	
-	#if BanAllEntityUsage
-		if ( this->isAborted ) XMP_Throw ( "DOCTYPE is not allowed", kXMPErr_BadXML );
-	#endif
-
-	if ( status != XML_STATUS_OK ) {
-	
-		XMP_StringPtr errMsg = "XML parsing failure";
-
-		#if 0	// XMP_DebugBuild	// Disable for now to make test output uniform. Restore later with thread safety.
-		
-			// *** This is a good candidate for a callback error notification mechanism.
-			// *** This code is not thread safe, the sExpatMessage isn't locked. But that's OK for debug usage.
-
-			enum XML_Error expatErr = XML_GetErrorCode ( this->parser );
-			const char *   expatMsg = XML_ErrorString ( expatErr );
-			int errLine = XML_GetCurrentLineNumber ( this->parser );
-		
-			char msgBuffer[1000];
-			// AUDIT: Use of sizeof(msgBuffer) for snprintf length is safe.
-			snprintf ( msgBuffer, sizeof(msgBuffer), "# Expat error %d at line %d, \"%s\"", expatErr, errLine, expatMsg );
-			sExpatMessage = msgBuffer;
-			errMsg = sExpatMessage.c_str();
-
-			#if  DumpXMLParseEvents
-				if ( this->parseLog != 0 ) fprintf ( this->parseLog, "%s\n", errMsg, expatErr, errLine, expatMsg );
-			#endif
-
-		#endif
-
-		XMP_Throw ( errMsg, kXMPErr_BadXML );
-
-	}
-	
-}	// ExpatAdapter::ParseBuffer
-
-// =================================================================================================
-// =================================================================================================
-
-#if XMP_DebugBuild & DumpXMLParseEvents
-
-	static inline void PrintIndent ( FILE * file, size_t count )
-	{
-		for ( ; count > 0; --count ) fprintf ( file, "  " );
-	}
-
-#endif
-
-// =================================================================================================
-
-static void SetQualName ( XMP_StringPtr fullName, XML_Node * node )
-{
-	// Expat delivers the full name as a catenation of namespace URI, separator, and local name.
-
-	// As a compatibility hack, an "about" or "ID" attribute of an rdf:Description element is
-	// changed to "rdf:about" or rdf:ID. Easier done here than in the RDF recognizer.
-	
-	// As a bug fix hack, change a URI of "http://purl.org/dc/1.1/" to ""http://purl.org/dc/elements/1.1/.
-	// Early versions of Flash that put XMP in SWF used a bad URI for the dc: namespace.
-
-	// ! This code presumes the RDF namespace prefix is "rdf".
-
-	size_t sepPos = strlen(fullName);
-	for ( --sepPos; sepPos > 0; --sepPos ) {
-		if ( fullName[sepPos] == FullNameSeparator ) break;
-	}
-
-	if ( fullName[sepPos] == FullNameSeparator ) {
-
-		XMP_StringPtr prefix;
-		XMP_StringLen prefixLen;
-		XMP_StringPtr localPart = fullName + sepPos + 1;
-
-		node->ns.assign ( fullName, sepPos );
-		if ( node->ns == "http://purl.org/dc/1.1/" ) node->ns = "http://purl.org/dc/elements/1.1/";
-
-		bool found = XMPMeta::GetNamespacePrefix ( node->ns.c_str(), &prefix, &prefixLen );
-		if ( ! found ) XMP_Throw ( "Unknown URI in Expat full name", kXMPErr_ExternalFailure );
-		node->nsPrefixLen = prefixLen;	// ! Includes the ':'.
-		
-		node->name = prefix;
-		node->name += localPart;
-
-	} else {
-
-		node->name = fullName;	// The name is not in a namespace.
-	
-		if ( node->parent->name == "rdf:Description" ) {
-			if ( node->name == "about" ) {
-				node->ns   = kXMP_NS_RDF;
-				node->name = "rdf:about";
-				node->nsPrefixLen = 4;	// ! Include the ':'.
-			} else if ( node->name == "ID" ) {
-				node->ns   = kXMP_NS_RDF;
-				node->name = "rdf:ID";
-				node->nsPrefixLen = 4;	// ! Include the ':'.
-			}
-		}
-		
-	}
-
-}	// SetQualName
-
-// =================================================================================================
-
-static void StartNamespaceDeclHandler ( void * userData, XMP_StringPtr prefix, XMP_StringPtr uri )
-{
-	IgnoreParam(userData);
-	
-	// As a bug fix hack, change a URI of "http://purl.org/dc/1.1/" to ""http://purl.org/dc/elements/1.1/.
-	// Early versions of Flash that put XMP in SWF used a bad URI for the dc: namespace.
-	
-	#if XMP_DebugBuild & DumpXMLParseEvents		// Avoid unused variable warning.
-		ExpatAdapter * thiz = (ExpatAdapter*)userData;
-	#endif
-
-	if ( prefix == 0 ) prefix = "_dflt_";	// Have default namespace.
-	if ( uri == 0 ) return;	// Ignore, have xmlns:pre="", no URI to register.
-	
-	#if XMP_DebugBuild & DumpXMLParseEvents
-		if ( thiz->parseLog != 0 ) {
-			PrintIndent ( thiz->parseLog, thiz->elemNesting );
-			fprintf ( thiz->parseLog, "StartNamespace: %s - \"%s\"\n", prefix, uri );
-		}
-	#endif
-	
-	if ( XMP_LitMatch ( uri, "http://purl.org/dc/1.1/" ) ) uri = "http://purl.org/dc/elements/1.1/";
-	XMPMeta::RegisterNamespace ( uri, prefix );
-
-}	// StartNamespaceDeclHandler
-
-// =================================================================================================
-
-static void EndNamespaceDeclHandler ( void * userData, XMP_StringPtr prefix )
-{
-	IgnoreParam(userData);
-
-	#if XMP_DebugBuild & DumpXMLParseEvents		// Avoid unused variable warning.
-		ExpatAdapter * thiz = (ExpatAdapter*)userData;
-	#endif
-
-	if ( prefix == 0 ) prefix = "_dflt_";	// Have default namespace.
-	
-	#if XMP_DebugBuild & DumpXMLParseEvents
-		if ( thiz->parseLog != 0 ) {
-			PrintIndent ( thiz->parseLog, thiz->elemNesting );
-			fprintf ( thiz->parseLog, "EndNamespace: %s\n", prefix );
-		}
-	#endif
-	
-	// ! Nothing to do, Expat has done all of the XML processing.
-
-}	// EndNamespaceDeclHandler
-
-// =================================================================================================
-
-static void StartElementHandler ( void * userData, XMP_StringPtr name, XMP_StringPtr* attrs )
-{
-	XMP_Assert ( attrs != 0 );
-	ExpatAdapter * thiz = (ExpatAdapter*)userData;
-	
-	size_t attrCount = 0;
-	for ( XMP_StringPtr* a = attrs; *a != 0; ++a ) ++attrCount;
-	if ( (attrCount & 1) != 0 )	XMP_Throw ( "Expat attribute info has odd length", kXMPErr_ExternalFailure );
-	attrCount = attrCount/2;	// They are name/value pairs.
-	
-	#if XMP_DebugBuild & DumpXMLParseEvents
-		if ( thiz->parseLog != 0 ) {
-			PrintIndent ( thiz->parseLog, thiz->elemNesting );
-			fprintf ( thiz->parseLog, "StartElement: %s, %d attrs", name, attrCount );
-			for ( XMP_StringPtr* attr = attrs; *attr != 0; attr += 2 ) {
-				XMP_StringPtr attrName = *attr;
-				XMP_StringPtr attrValue = *(attr+1);
-				fprintf ( thiz->parseLog, ", %s = \"%s\"", attrName, attrValue );
-			}
-			fprintf ( thiz->parseLog, "\n" );
-		}
-	#endif
-
-	XML_Node * parentNode = thiz->parseStack.back();
-	XML_Node * elemNode   = new XML_Node ( parentNode, "", kElemNode );
-	
-	SetQualName ( name, elemNode );
-	
-	for ( XMP_StringPtr* attr = attrs; *attr != 0; attr += 2 ) {
-
-		XMP_StringPtr attrName = *attr;
-		XMP_StringPtr attrValue = *(attr+1);
-		XML_Node * attrNode = new XML_Node ( elemNode, "", kAttrNode );
-
-		SetQualName ( attrName, attrNode );
-		attrNode->value = attrValue;
-		if ( attrNode->name == "xml:lang" ) NormalizeLangValue ( &attrNode->value );
-		elemNode->attrs.push_back ( attrNode );
-
-	}
-	
-	parentNode->content.push_back ( elemNode );
-	thiz->parseStack.push_back ( elemNode );
-	
-	if ( elemNode->name == "rdf:RDF" ) {
-		thiz->rootNode = elemNode;
-		++thiz->rootCount;
-	}
-	#if XMP_DebugBuild
-		++thiz->elemNesting;
-	#endif
-
-}	// StartElementHandler
-
-// =================================================================================================
-
-static void EndElementHandler ( void * userData, XMP_StringPtr name )
-{
-	IgnoreParam(name);
-	
-	ExpatAdapter * thiz = (ExpatAdapter*)userData;
-
-	#if XMP_DebugBuild
-		--thiz->elemNesting;
-	#endif
-	(void) thiz->parseStack.pop_back();
-	
-	#if XMP_DebugBuild & DumpXMLParseEvents
-		if ( thiz->parseLog != 0 ) {
-			PrintIndent ( thiz->parseLog, thiz->elemNesting );
-			fprintf ( thiz->parseLog, "EndElement: %s\n", name );
-		}
-	#endif
-
-}	// EndElementHandler
-
-// =================================================================================================
-
-static void CharacterDataHandler ( void * userData, XMP_StringPtr cData, int len )
-{
-	ExpatAdapter * thiz = (ExpatAdapter*)userData;
-	
-	if ( (cData == 0) || (len == 0) ) { cData = ""; len = 0; }
-	
-	#if XMP_DebugBuild & DumpXMLParseEvents
-		if ( thiz->parseLog != 0 ) {
-			PrintIndent ( thiz->parseLog, thiz->elemNesting );
-			fprintf ( thiz->parseLog, "CharContent: \"" );
-			for ( int i = 0; i < len; ++i ) fprintf ( thiz->parseLog, "%c", cData[i] );
-			fprintf ( thiz->parseLog, "\"\n" );
-		}
-	#endif
-	
-	XML_Node * parentNode = thiz->parseStack.back();
-	XML_Node * cDataNode  = new XML_Node ( parentNode, "", kCDataNode );
-	
-	cDataNode->value.assign ( cData, len );
-	parentNode->content.push_back ( cDataNode );
-	
-}	// CharacterDataHandler
-
-// =================================================================================================
-
-static void StartCdataSectionHandler ( void * userData )
-{
-	IgnoreParam(userData);
-
-	#if XMP_DebugBuild & DumpXMLParseEvents		// Avoid unused variable warning.
-		ExpatAdapter * thiz = (ExpatAdapter*)userData;
-	#endif
-	
-	#if XMP_DebugBuild & DumpXMLParseEvents
-		if ( thiz->parseLog != 0 ) {
-			PrintIndent ( thiz->parseLog, thiz->elemNesting );
-			fprintf ( thiz->parseLog, "StartCDATA\n" );
-		}
-	#endif
-	
-	// *** Since markup isn't recognized inside CDATA, this affects XMP's double escaping.
-	
-}	// StartCdataSectionHandler
-
-// =================================================================================================
-
-static void EndCdataSectionHandler ( void * userData )
-{
-	IgnoreParam(userData);
-
-	#if XMP_DebugBuild & DumpXMLParseEvents		// Avoid unused variable warning.
-		ExpatAdapter * thiz = (ExpatAdapter*)userData;
-	#endif
-	
-	#if XMP_DebugBuild & DumpXMLParseEvents
-		if ( thiz->parseLog != 0 ) {
-			PrintIndent ( thiz->parseLog, thiz->elemNesting );
-			fprintf ( thiz->parseLog, "EndCDATA\n" );
-		}
-	#endif	
-
-}	// EndCdataSectionHandler
-
-// =================================================================================================
-
-static void ProcessingInstructionHandler ( void * userData, XMP_StringPtr target, XMP_StringPtr data )
-{
-	XMP_Assert ( target != 0 );
-	ExpatAdapter * thiz = (ExpatAdapter*)userData;
-
-	if ( ! XMP_LitMatch ( target, "xpacket" ) ) return;	// Ignore all PIs except the XMP packet wrapper.
-	if ( data == 0 ) data = "";
-	
-	#if XMP_DebugBuild & DumpXMLParseEvents
-		if ( thiz->parseLog != 0 ) {
-			PrintIndent ( thiz->parseLog, thiz->elemNesting );
-			fprintf ( thiz->parseLog, "PI: %s - \"%s\"\n", target, data );
-		}
-	#endif
-	
-	XML_Node * parentNode = thiz->parseStack.back();
-	XML_Node * piNode  = new XML_Node ( parentNode, target, kPINode );
-	
-	piNode->value.assign ( data );
-	parentNode->content.push_back ( piNode );
-	
-}	// ProcessingInstructionHandler
-
-// =================================================================================================
-
-static void CommentHandler ( void * userData, XMP_StringPtr comment )
-{
-	IgnoreParam(userData);
-
-	#if XMP_DebugBuild & DumpXMLParseEvents		// Avoid unused variable warning.
-		ExpatAdapter * thiz = (ExpatAdapter*)userData;
-	#endif
-
-	if ( comment == 0 ) comment = "";
-	
-	#if XMP_DebugBuild & DumpXMLParseEvents
-		if ( thiz->parseLog != 0 ) {
-			PrintIndent ( thiz->parseLog, thiz->elemNesting );
-			fprintf ( thiz->parseLog, "Comment: \"%s\"\n", comment );
-		}
-	#endif
-	
-	// ! Comments are ignored.
-	
-}	// CommentHandler
-
-// =================================================================================================
-
-#if BanAllEntityUsage
-static void StartDoctypeDeclHandler ( void * userData, XMP_StringPtr doctypeName,
-									  XMP_StringPtr sysid, XMP_StringPtr pubid, int has_internal_subset )
-{
-	IgnoreParam(userData);
-
-	ExpatAdapter * thiz = (ExpatAdapter*)userData;
-
-	#if XMP_DebugBuild & DumpXMLParseEvents		// Avoid unused variable warning.
-		if ( thiz->parseLog != 0 ) {
-			PrintIndent ( thiz->parseLog, thiz->elemNesting );
-			fprintf ( thiz->parseLog, "DocType: \"%s\"\n", doctypeName );
-		}
-	#endif
-	
-	thiz->isAborted = true;	// ! Can't throw an exception across the plain C Expat frames.
-	(void) XML_StopParser ( thiz->parser, XML_FALSE /* not resumable */ );
-
-}	// StartDoctypeDeclHandler
-#endif
-
-// =================================================================================================
diff --git a/xmpsdk/src/ExpatAdapter.hpp b/xmpsdk/src/ExpatAdapter.hpp
deleted file mode 100644
index 9d6c9ec4..00000000
--- a/xmpsdk/src/ExpatAdapter.hpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef __ExpatAdapter_hpp__
-#define __ExpatAdapter_hpp__
-
-// =================================================================================================
-// Copyright 2005-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! Must be the first #include!
-#include "XMLParserAdapter.hpp"
-
-// =================================================================================================
-// Derived XML parser adapter for Expat.
-// =================================================================================================
-
-#ifndef BanAllEntityUsage
-	#define BanAllEntityUsage	0
-#endif
-
-struct XML_ParserStruct;	// ! Hack to avoid exposing expat.h to all clients.
-typedef struct XML_ParserStruct *XML_Parser;
-
-class ExpatAdapter : public XMLParserAdapter {
-public:
-
-	XML_Parser parser;
-	
-	#if BanAllEntityUsage
-		bool isAborted;
-	#endif
-	
-	#if XMP_DebugBuild
-		size_t elemNesting;
-	#endif
-	
-	ExpatAdapter();
-	virtual ~ExpatAdapter();
-	
-	void ParseBuffer ( const void * buffer, size_t length, bool last = true );
-
-};
-
-extern "C" ExpatAdapter * XMP_NewExpatAdapter();
-
-// =================================================================================================
-
-#endif	// __ExpatAdapter_hpp__
diff --git a/xmpsdk/src/Makefile b/xmpsdk/src/Makefile
deleted file mode 100644
index c18e9656..00000000
--- a/xmpsdk/src/Makefile
+++ /dev/null
@@ -1,153 +0,0 @@
-# ************************************************************* -*- Makefile -*-
-#
-# Copyright (C) 2004-2015 Andreas Huggel <ahuggel@gmx.net>
-#
-# This Makefile is part of the Exiv2 distribution.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-#    1. Redistributions of source code must retain the above copyright
-#       notice, this list of conditions and the following disclaimer.
-#    2. Redistributions in binary form must reproduce the above
-#       copyright notice, this list of conditions and the following
-#       disclaimer in the documentation and/or other materials provided
-#       with the distribution.
-#    3. The name of the author may not be used to endorse or promote
-#       products derived from this software without specific prior
-#       written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
-# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
-# GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
-# IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
-# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-# File:      Makefile
-# Version:   $Rev$
-# Author(s): Andreas Huggel (ahu) <ahuggel@gmx.net>
-# History:   30-Sep-07, ahu: created
-#
-# Description:
-#  Makefile to build the Adobe XMP Toolkit integrated and distributed with
-#  Exiv2. Adapted from the main Exiv2 src/Makefile. This builds what the
-#  libtool manual calls a "convenience library".
-#
-# Restrictions:
-#  Requires GNU make.
-#
-
-# Default make target
-all: xmpsdk
-
-# Include system configuration
-top_srcdir = ../..
-include $(top_srcdir)/config/config.mk
-
-# ******************************************************************************
-# Source files
-
-# Add library C++ source files to this list
-CCSRC = XML_Node.cpp           \
-        XMPMeta.cpp            \
-        XMPMeta-GetSet.cpp     \
-        XMPMeta-Parse.cpp      \
-        XMPMeta-Serialize.cpp  \
-        XMPIterator.cpp        \
-        XMPUtils.cpp           \
-        XMPUtils-FileInfo.cpp  \
-        XMPCore_Impl.cpp       \
-        ExpatAdapter.cpp       \
-        ParseRDF.cpp           \
-        UnicodeConversions.cpp \
-        MD5.cpp                \
-        WXMPMeta.cpp           \
-        WXMPIterator.cpp       \
-        WXMPUtils.cpp
-
-# ******************************************************************************
-# Library
-LIBRARY := lib$(XMPSDK_LIBRARY).la
-
-# ******************************************************************************
-# Initialisations
-SHELL = /bin/sh
-
-.SUFFIXES:
-.SUFFIXES: .c .cpp .o .so
-
-.PRECIOUS: %.cpp
-
-# For a debug build, replace -DNDEBUG=1 with -DDEBUG=1 -D_DEBUG=1
-CPPFLAGS += -I../include -funsigned-char -DNDEBUG=1 $(EXPAT_CPPFLAGS)
-ifdef HAVE_STDINT
-	CPPFLAGS += -DEXV_HAVE_STDINT_H=1
-endif
-
-LDFLAGS += $(EXPAT_LDFLAGS)
-LIBS += $(EXPAT_LIBS)
-
-# Generic variables
-CCOBJ = $(CCSRC:.cpp=.o)
-LOBJ = $(CCSRC:.cpp=.lo)
-
-ifdef DEP_TRACKING
-DEP = $(CCSRC:%.cpp=$(DEPDIR)/%.d)
-endif
-
-# ******************************************************************************
-# Rules
-$(CCOBJ): %.o: %.cpp
-	@$(LIBTOOL) --mode=compile $(COMPILE.cc) -o $@ $<
-	@$(MAKEDEPEND)
-	@$(POSTDEPEND)
-
-%.ii: %.cpp
-	set -e; \
-	$(CXXCPP) $(CPPFLAGS) $< | sed '/^[ 	]*$$/d' > $@
-
-# ******************************************************************************
-# Targets
-.PHONY: all mostlyclean clean distclean maintainer-clean
-
-ifdef DEP_TRACKING
-# Include targets from dependency files
--include $(DEP)
-endif
-
-$(LIBTOOL): $(LIBTOOL_DEPS)
-	$(SHELL) $(top_srcdir)/config.status --recheck
-
-xmpsdk: $(LIBRARY)
-
-$(LIBRARY): $(CCOBJ)
-	$(LIBTOOL) --mode=link $(LINK.cc) -o $(LIBRARY) $(LOBJ)
-
-mostlyclean:
-	$(RM) core
-	$(RM) $(CCSRC:.cpp=.ii)
-	$(RM) $(CCSRC:%.cpp=.libs/%.d)
-	@$(LIBTOOL) --mode=clean $(RM) $(LOBJ)
-
-clean: mostlyclean
-	@$(LIBTOOL) --mode=clean $(RM) $(LIBRARY)
-
-# Run `make distclean' from the top source directory to also remove
-# files created by configuring the program.
-distclean: clean
-ifdef DEP_TRACKING
-	$(RM) $(DEP)
-	-rmdir $(DEPDIR)
-endif
-	$(RM) *~ *.bak *#
-
-# This command is intended for maintainers to use; it deletes files
-# that may need special tools to rebuild.
-maintainer-clean: distclean
diff --git a/xmpsdk/src/ParseRDF.cpp b/xmpsdk/src/ParseRDF.cpp
deleted file mode 100644
index c47ffd73..00000000
--- a/xmpsdk/src/ParseRDF.cpp
+++ /dev/null
@@ -1,1296 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-#include "ExpatAdapter.hpp"
-
-#include <cstring>
-
-#if DEBUG
-	#include <iostream>
-#endif
-
-using namespace std;
-
-#if XMP_WinBuild
-#   ifdef _MSC_VER
-        #pragma warning ( disable : 4189 )	// local variable is initialized but not referenced
-        #pragma warning ( disable : 4505 )	// unreferenced local function has been removed
-#   endif
-#endif
-
-// =================================================================================================
-
-// *** This might be faster and use less memory as a state machine. A big advantage of building an
-// *** XML tree though is easy lookahead during the recursive descent processing.
-
-// *** It would be nice to give a line number or byte offset in the exception messages.
-
-
-// 7 RDF/XML Grammar (from http://www.w3.org/TR/rdf-syntax-grammar/#section-Infoset-Grammar)
-//
-// 7.1 Grammar summary
-//
-// 7.2.2 coreSyntaxTerms
-//		rdf:RDF | rdf:ID | rdf:about | rdf:parseType | rdf:resource | rdf:nodeID | rdf:datatype
-//
-// 7.2.3 syntaxTerms
-//		coreSyntaxTerms | rdf:Description | rdf:li
-//
-// 7.2.4 oldTerms
-//		rdf:aboutEach | rdf:aboutEachPrefix | rdf:bagID
-//
-// 7.2.5 nodeElementURIs
-//		anyURI - ( coreSyntaxTerms | rdf:li | oldTerms )
-//
-// 7.2.6 propertyElementURIs
-//		anyURI - ( coreSyntaxTerms | rdf:Description | oldTerms )
-//
-// 7.2.7 propertyAttributeURIs
-//		anyURI - ( coreSyntaxTerms | rdf:Description | rdf:li | oldTerms )
-//
-// 7.2.8 doc
-//		root ( document-element == RDF, children == list ( RDF ) )
-//
-// 7.2.9 RDF
-//		start-element ( URI == rdf:RDF, attributes == set() )
-//		nodeElementList
-//		end-element()
-//
-// 7.2.10 nodeElementList
-//		ws* ( nodeElement ws* )*
-//
-// 7.2.11 nodeElement
-//		start-element ( URI == nodeElementURIs,
-//						attributes == set ( ( idAttr | nodeIdAttr | aboutAttr )?, propertyAttr* ) )
-//		propertyEltList
-//		end-element()
-//
-// 7.2.12 ws
-//		A text event matching white space defined by [XML] definition White Space Rule [3] S in section Common Syntactic Constructs.
-//
-// 7.2.13 propertyEltList
-//		ws* ( propertyElt ws* )*
-//
-// 7.2.14 propertyElt
-//		resourcePropertyElt | literalPropertyElt | parseTypeLiteralPropertyElt |
-//		parseTypeResourcePropertyElt | parseTypeCollectionPropertyElt | parseTypeOtherPropertyElt | emptyPropertyElt
-//
-// 7.2.15 resourcePropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr? ) )
-//		ws* nodeElement ws*
-//		end-element()
-//
-// 7.2.16 literalPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, datatypeAttr?) )
-//		text()
-//		end-element()
-//
-// 7.2.17 parseTypeLiteralPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseLiteral ) )
-//		literal
-//		end-element()
-//
-// 7.2.18 parseTypeResourcePropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseResource ) )
-//		propertyEltList
-//		end-element()
-//
-// 7.2.19 parseTypeCollectionPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseCollection ) )
-//		nodeElementList
-//		end-element()
-//
-// 7.2.20 parseTypeOtherPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseOther ) )
-//		propertyEltList
-//		end-element()
-//
-// 7.2.21 emptyPropertyElt
-//		start-element ( URI == propertyElementURIs,
-//						attributes == set ( idAttr?, ( resourceAttr | nodeIdAttr )?, propertyAttr* ) )
-//		end-element()
-//
-// 7.2.22 idAttr
-//		attribute ( URI == rdf:ID, string-value == rdf-id )
-//
-// 7.2.23 nodeIdAttr
-//		attribute ( URI == rdf:nodeID, string-value == rdf-id )
-//
-// 7.2.24 aboutAttr
-//		attribute ( URI == rdf:about, string-value == URI-reference )
-//
-// 7.2.25 propertyAttr
-//		attribute ( URI == propertyAttributeURIs, string-value == anyString )
-//
-// 7.2.26 resourceAttr
-//		attribute ( URI == rdf:resource, string-value == URI-reference )
-//
-// 7.2.27 datatypeAttr
-//		attribute ( URI == rdf:datatype, string-value == URI-reference )
-//
-// 7.2.28 parseLiteral
-//		attribute ( URI == rdf:parseType, string-value == "Literal")
-//
-// 7.2.29 parseResource
-//		attribute ( URI == rdf:parseType, string-value == "Resource")
-//
-// 7.2.30 parseCollection
-//		attribute ( URI == rdf:parseType, string-value == "Collection")
-//
-// 7.2.31 parseOther
-//		attribute ( URI == rdf:parseType, string-value == anyString - ("Resource" | "Literal" | "Collection") )
-//
-// 7.2.32 URI-reference
-//		An RDF URI Reference.
-//
-// 7.2.33 literal
-//		Any XML element content that is allowed according to [XML] definition Content of Elements Rule [43] content
-//		in section 3.1 Start-Tags, End-Tags, and Empty-Element Tags.
-//
-// 7.2.34 rdf-id
-//		An attribute string-value matching any legal [XML-NS] token NCName.
-
-
-// =================================================================================================
-// Primary Parsing Functions
-// =========================
-//
-// Each of these is responsible for recognizing an RDF syntax production and adding the appropriate
-// structure to the XMP tree. They simply return for success, failures will throw an exception.
-
-static void
-RDF_RDF ( XMP_Node * xmpTree, const XML_Node & xmlNode );
-
-static void
-RDF_NodeElementList ( XMP_Node * xmpParent, const XML_Node & xmlParent, bool isTopLevel );
-
-static void
-RDF_NodeElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel );
-
-static void
-RDF_NodeElementAttrs ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel );
-
-static void
-RDF_PropertyElementList ( XMP_Node * xmpParent, const XML_Node & xmlParent, bool isTopLevel );
-enum { kIsTopLevel = true, kNotTopLevel = false };
-
-static void
-RDF_PropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel );
-
-static void
-RDF_ResourcePropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel );
-
-static void
-RDF_LiteralPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel );
-
-static void
-RDF_ParseTypeLiteralPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel );
-
-static void
-RDF_ParseTypeResourcePropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel );
-
-static void
-RDF_ParseTypeCollectionPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel );
-
-static void
-RDF_ParseTypeOtherPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel );
-
-static void
-RDF_EmptyPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel );
-
-
-// =================================================================================================
-
-typedef XMP_Uns8 RDFTermKind;
-
-// *** Logic might be safer with just masks.
-
-enum {
-	kRDFTerm_Other				=  0,
-	kRDFTerm_RDF				=  1,	// Start of coreSyntaxTerms.
-	kRDFTerm_ID					=  2,
-	kRDFTerm_about				=  3,
-	kRDFTerm_parseType			=  4,
-	kRDFTerm_resource			=  5,
-	kRDFTerm_nodeID				=  6,
-	kRDFTerm_datatype			=  7,	// End of coreSyntaxTerms.
-	kRDFTerm_Description		=  8,	// Start of additions for syntaxTerms.
-	kRDFTerm_li					=  9,	// End of of additions for syntaxTerms.
-	kRDFTerm_aboutEach			= 10,	// Start of oldTerms.
-	kRDFTerm_aboutEachPrefix	= 11,
-	kRDFTerm_bagID				= 12,	// End of oldTerms.
-	
-	kRDFTerm_FirstCore          = kRDFTerm_RDF,
-	kRDFTerm_LastCore           = kRDFTerm_datatype,
-	kRDFTerm_FirstSyntax        = kRDFTerm_FirstCore,	// ! Yes, the syntax terms include the core terms.
-	kRDFTerm_LastSyntax         = kRDFTerm_li,
-	kRDFTerm_FirstOld           = kRDFTerm_aboutEach,
-	kRDFTerm_LastOld            = kRDFTerm_bagID
-};
-
-enum {
-	kRDFMask_Other				= 1 << kRDFTerm_Other,
-	kRDFMask_RDF				= 1 << kRDFTerm_RDF,
-	kRDFMask_ID					= 1 << kRDFTerm_ID,
-	kRDFMask_about				= 1 << kRDFTerm_about,
-	kRDFMask_parseType			= 1 << kRDFTerm_parseType,
-	kRDFMask_resource			= 1 << kRDFTerm_resource,
-	kRDFMask_nodeID				= 1 << kRDFTerm_nodeID,
-	kRDFMask_datatype			= 1 << kRDFTerm_datatype,
-	kRDFMask_Description		= 1 << kRDFTerm_Description,
-	kRDFMask_li					= 1 << kRDFTerm_li,
-	kRDFMask_aboutEach			= 1 << kRDFTerm_aboutEach,
-	kRDFMask_aboutEachPrefix	= 1 << kRDFTerm_aboutEachPrefix,
-	kRDFMask_bagID				= 1 << kRDFTerm_bagID
-};
-
-enum {
-	kRDF_HasValueElem = 0x10000000UL	// ! Contains rdf:value child. Must fit within kXMP_ImplReservedMask!
-};
-
-// -------------------------------------------------------------------------------------------------
-// GetRDFTermKind
-// --------------
-
-static RDFTermKind
-GetRDFTermKind ( const XMP_VarString & name )
-{
-	RDFTermKind term = kRDFTerm_Other;
-
-	// Arranged to hopefully minimize the parse time for large XMP.
-
-	if ( (name.size() > 4) && (strncmp ( name.c_str(), "rdf:", 4 ) == 0) ) {
-
-		if ( name == "rdf:li" ) {
-			term = kRDFTerm_li;
-		} else if ( name == "rdf:parseType" ) {
-			term = kRDFTerm_parseType;
-		} else if ( name == "rdf:Description" ) {
-			term = kRDFTerm_Description;
-		} else if ( name == "rdf:about" ) {
-			term = kRDFTerm_about;
-		} else if ( name == "rdf:resource" ) {
-			term = kRDFTerm_resource;
-		} else if ( name == "rdf:RDF" ) {
-			term = kRDFTerm_RDF;
-		} else if ( name == "rdf:ID" ) {
-			term = kRDFTerm_ID;
-		} else if ( name == "rdf:nodeID" ) {
-			term = kRDFTerm_nodeID;
-		} else if ( name == "rdf:datatype" ) {
-			term = kRDFTerm_datatype;
-		} else if ( name == "rdf:aboutEach" ) {
-			term = kRDFTerm_aboutEach;
-		} else if ( name == "rdf:aboutEachPrefix" ) {
-			term = kRDFTerm_aboutEachPrefix;
-		} else if ( name == "rdf:bagID" ) {
-			term = kRDFTerm_bagID;
-		}
-
-	}
-
-	return term;
-
-}	// GetRDFTermKind
-
-
-// =================================================================================================
-
-
-// -------------------------------------------------------------------------------------------------
-// IsCoreSyntaxTerm
-// ----------------
-//
-// 7.2.2 coreSyntaxTerms
-//		rdf:RDF | rdf:ID | rdf:about | rdf:parseType | rdf:resource | rdf:nodeID | rdf:datatype
-
-static bool
-IsCoreSyntaxTerm ( RDFTermKind term )
-{
-
-	if 	( (kRDFTerm_FirstCore <= term) && (term <= kRDFTerm_LastCore) ) return true;
-	return false;
-
-}	// IsCoreSyntaxTerm
-
-
-// -------------------------------------------------------------------------------------------------
-// IsOldTerm
-// ---------
-//
-// 7.2.4 oldTerms
-//		rdf:aboutEach | rdf:aboutEachPrefix | rdf:bagID
-
-static bool
-IsOldTerm ( RDFTermKind term )
-{
-
-	if 	( (kRDFTerm_FirstOld <= term) && (term <= kRDFTerm_LastOld) ) return true;
-	return false;
-
-}	// IsOldTerm
-
-// -------------------------------------------------------------------------------------------------
-// IsPropertyElementName
-// ---------------------
-//
-// 7.2.6 propertyElementURIs
-//		anyURI - ( coreSyntaxTerms | rdf:Description | oldTerms )
-
-static bool
-IsPropertyElementName ( RDFTermKind term )
-{
-
-	if 	( (term == kRDFTerm_Description) || IsOldTerm ( term ) ) return false;
-	return (! IsCoreSyntaxTerm ( term ));
-
-}	// IsPropertyElementName
-
-// =================================================================================================
-// AddChildNode
-// ============
-
-static XMP_Node *
-AddChildNode ( XMP_Node * xmpParent, const XML_Node & xmlNode, const XMP_StringPtr value, bool isTopLevel )
-{
-	#if 0
-		cout << "AddChildNode, parent = " << xmpParent->name << ", child = " << xmlNode.name;
-		cout << ", value = \"" << value << '"';
-		if ( isTopLevel ) cout << ", top level";
-		cout << endl;
-	#endif
-	
-	if ( xmlNode.ns.empty() ) {
-		XMP_Throw ( "XML namespace required for all elements and attributes", kXMPErr_BadRDF );
-	}
-		
-	XMP_StringPtr  childName    = xmlNode.name.c_str();
-	const bool     isArrayItem  = (xmlNode.name == "rdf:li");
-	const bool     isValueNode  = (xmlNode.name == "rdf:value");
-	XMP_OptionBits childOptions = 0;
-	
-	if ( isTopLevel ) {
-
-		// Lookup the schema node, adjust the XMP parent pointer.
-		XMP_Assert ( xmpParent->parent == 0 );	// Incoming parent must be the tree root.
-		XMP_Node * schemaNode = FindSchemaNode ( xmpParent, xmlNode.ns.c_str(), kXMP_CreateNodes );
-		if ( schemaNode->options & kXMP_NewImplicitNode ) schemaNode->options ^= kXMP_NewImplicitNode;	// Clear the implicit node bit.
-			// *** Should use "opt &= ~flag" (no conditional), need runtime check for proper 32 bit code.
-		xmpParent = schemaNode;
-		
-		// If this is an alias set the isAlias flag in the node and the hasAliases flag in the tree.
-		if ( sRegisteredAliasMap->find ( xmlNode.name ) != sRegisteredAliasMap->end() ) {
-			childOptions |= kXMP_PropIsAlias;
-			schemaNode->parent->options |= kXMP_PropHasAliases;
-		}
-		
-	}
-
-	// Make sure that this is not a duplicate of a named node.
-	if ( ! (isArrayItem | isValueNode) ) {
-		if ( FindChildNode ( xmpParent, childName, kXMP_ExistingOnly ) != 0 ) {
-			XMP_Throw ( "Duplicate property or field node", kXMPErr_BadXMP );
-		}
-		
-	}
-	
-	// Add the new child to the XMP parent node.
-	XMP_Node * newChild = new XMP_Node ( xmpParent, childName, value, childOptions );
-	if ( (! isValueNode) || xmpParent->children.empty() ) {
-		 xmpParent->children.push_back ( newChild );
-	} else {
-		 xmpParent->children.insert ( xmpParent->children.begin(), newChild );
-	}
-	if ( isValueNode ) {
-		if ( isTopLevel || (! (xmpParent->options & kXMP_PropValueIsStruct)) ) XMP_Throw ( "Misplaced rdf:value element", kXMPErr_BadRDF );
-		xmpParent->options |= kRDF_HasValueElem;
-	}
-	
-	if ( isArrayItem ) {
-		if ( ! (xmpParent->options & kXMP_PropValueIsArray) ) XMP_Throw ( "Misplaced rdf:li element", kXMPErr_BadRDF );
-		newChild->name = kXMP_ArrayItemName;
-		#if 0	// *** XMP_DebugBuild
-			newChild->_namePtr = newChild->name.c_str();
-		#endif
-	}
-	
-	return newChild;
-
-}	// AddChildNode
-
-
-// =================================================================================================
-// AddQualifierNode
-// ================
-
-static XMP_Node *
-AddQualifierNode ( XMP_Node * xmpParent, const XMP_VarString & name, const XMP_VarString & value )
-{
-
-	#if 0
-		cout << "AddQualifierNode, parent = " << xmpParent->name << ", name = " << name;
-		cout << ", value = \"" << value << '"' << endl;
-	#endif
-	
-	const bool isLang = (name == "xml:lang");
-	const bool isType = (name == "rdf:type");
-
-	XMP_Node * newQual = 0;
-
-		newQual = new XMP_Node ( xmpParent, name, value, kXMP_PropIsQualifier );
-
-		if ( ! (isLang | isType) ) {
-			xmpParent->qualifiers.push_back ( newQual );
-		} else if ( isLang ) {
-			if ( xmpParent->qualifiers.empty() ) {
-				xmpParent->qualifiers.push_back ( newQual );
-			} else {
-				xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin(), newQual );
-			}
-			xmpParent->options |= kXMP_PropHasLang;
-		} else {
-			XMP_Assert ( isType );
-			if ( xmpParent->qualifiers.empty() ) {
-				xmpParent->qualifiers.push_back ( newQual );
-			} else {
-				size_t offset = 0;
-				if ( XMP_PropHasLang ( xmpParent->options ) ) offset = 1;
-				xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin()+offset, newQual );
-			}
-			xmpParent->options |= kXMP_PropHasType;
-		}
-
-		xmpParent->options |= kXMP_PropHasQualifiers;
-
-	return newQual;
-
-}	// AddQualifierNode
-
-
-// =================================================================================================
-// AddQualifierNode
-// ================
-
-static XMP_Node *
-AddQualifierNode ( XMP_Node * xmpParent, const XML_Node & attr )
-{
-	if ( attr.ns.empty() ) {
-		XMP_Throw ( "XML namespace required for all elements and attributes", kXMPErr_BadRDF );
-	}
-	
-	return AddQualifierNode ( xmpParent, attr.name, attr.value );
-
-}	// AddQualifierNode
-
-
-// =================================================================================================
-// FixupQualifiedNode
-// ==================
-//
-// The parent is an RDF pseudo-struct containing an rdf:value field. Fix the XMP data model. The
-// rdf:value node must be the first child, the other children are qualifiers. The form, value, and
-// children of the rdf:value node are the real ones. The rdf:value node's qualifiers must be added
-// to the others.
-	
-static void
-FixupQualifiedNode ( XMP_Node * xmpParent )
-{
-	size_t qualNum, qualLim;
-	size_t childNum, childLim;
-
-	XMP_Enforce ( (xmpParent->options & kXMP_PropValueIsStruct) && (! xmpParent->children.empty()) );
-
-	XMP_Node * valueNode = xmpParent->children[0];
-	XMP_Enforce ( valueNode->name == "rdf:value" );
-	
-	xmpParent->qualifiers.reserve ( xmpParent->qualifiers.size() + xmpParent->children.size() + valueNode->qualifiers.size() );
-	
-	// Move the qualifiers on the value node to the parent. Make sure an xml:lang qualifier stays at
-	// the front. Check for duplicate names between the value node's qualifiers and the parent's
-	// children. The parent's children are about to become qualifiers. Check here, between the
-	// groups. Intra-group duplicates are caught by AddChildNode.
-	
-	qualNum = 0;
-	qualLim = valueNode->qualifiers.size();
-	
-	if ( valueNode->options & kXMP_PropHasLang ) {
-
-		if ( xmpParent->options & kXMP_PropHasLang ) XMP_Throw ( "Redundant xml:lang for rdf:value element", kXMPErr_BadXMP );
-
-		XMP_Node * langQual = valueNode->qualifiers[0];
-		
-		XMP_Assert ( langQual->name == "xml:lang" );
-		langQual->parent = xmpParent;
-		xmpParent->options |= kXMP_PropHasLang;
-
-		if ( xmpParent->qualifiers.empty() ) {
-			xmpParent->qualifiers.push_back ( langQual );	// *** Should use utilities to add qual & set parent.
-		} else {
-			xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin(), langQual );
-		}
-		valueNode->qualifiers[0] = 0;	// We just moved it to the parent.
-
-		qualNum = 1;	// Start the remaining copy after the xml:lang qualifier.
-
-	}
-	
-	for ( ; qualNum != qualLim; ++qualNum ) {
-
-		XMP_Node * currQual = valueNode->qualifiers[qualNum];
-		if ( FindChildNode ( xmpParent, currQual->name.c_str(), kXMP_ExistingOnly ) != 0 ) {
-			XMP_Throw ( "Duplicate qualifier node", kXMPErr_BadXMP );
-		}
-
-		currQual->parent = xmpParent;
-		xmpParent->qualifiers.push_back ( currQual );
-		valueNode->qualifiers[qualNum] = 0;	// We just moved it to the parent.
-
-	}
-	
-	valueNode->qualifiers.clear();	// ! There should be nothing but null pointers.
-	
-	// Change the parent's other children into qualifiers. This loop starts at 1, child 0 is the
-	// rdf:value node. Put xml:lang at the front, append all others.
-	
-	for ( childNum = 1, childLim = xmpParent->children.size(); childNum != childLim; ++childNum ) {
-
-		XMP_Node * currQual = xmpParent->children[childNum];
-	
-			bool isLang = (currQual->name == "xml:lang");
-			
-			currQual->options |= kXMP_PropIsQualifier;
-			currQual->parent = xmpParent;
-
-			if ( isLang ) {
-				if ( xmpParent->options & kXMP_PropHasLang ) XMP_Throw ( "Duplicate xml:lang qualifier", kXMPErr_BadXMP );
-				xmpParent->options |= kXMP_PropHasLang;
-			} else if ( currQual->name == "rdf:type" ) {
-				xmpParent->options |= kXMP_PropHasType;
-			}
-
-			if ( (! isLang) || xmpParent->qualifiers.empty() ) {
-				xmpParent->qualifiers.push_back ( currQual );
-			} else {
-				xmpParent->qualifiers.insert ( xmpParent->qualifiers.begin(), currQual );
-			}
-			xmpParent->children[childNum] = 0;	// We just moved it to the qualifers.
-		
-	}
-	
-	if ( ! xmpParent->qualifiers.empty() ) xmpParent->options |= kXMP_PropHasQualifiers;
-	
-	// Move the options and value last, other checks need the parent's original options. Move the
-	// value node's children to be the parent's children. Delete the now useless value node.
-	
-	XMP_Assert ( xmpParent->options & (kXMP_PropValueIsStruct | kRDF_HasValueElem) );
-	xmpParent->options &= ~ (kXMP_PropValueIsStruct | kRDF_HasValueElem);
-	xmpParent->options |= valueNode->options;
-	
-	xmpParent->value.swap ( valueNode->value );
-	#if 0	// *** XMP_DebugBuild
-		xmpParent->_valuePtr = xmpParent->value.c_str();
-	#endif
-
-	xmpParent->children[0] = 0;	// ! Remove the value node itself before the swap.
-	xmpParent->children.swap ( valueNode->children );
-	
-	for ( size_t childNum = 0, childLim = xmpParent->children.size(); childNum != childLim; ++childNum ) {
-		XMP_Node * currChild = xmpParent->children[childNum];
-		currChild->parent = xmpParent;
-	}
-
-	delete valueNode;
-	
-}	// FixupQualifiedNode
-
-
-// =================================================================================================
-// ProcessRDF
-// ==========
-//
-// Parse the XML tree of the RDF and build the corresponding XMP tree.
-
-// *** Throw an exception if no XMP is found? By option?
-// *** Do parsing exceptions cause the partial tree to be deleted?
-
-void ProcessRDF ( XMP_Node * xmpTree, const XML_Node & rdfNode, XMP_OptionBits options )
-{
-	IgnoreParam(options);
-	
-	RDF_RDF ( xmpTree, rdfNode );
-
-}	// ProcessRDF
-
-
-// =================================================================================================
-// RDF_RDF
-// =======
-//
-// 7.2.9 RDF
-//		start-element ( URI == rdf:RDF, attributes == set() )
-//		nodeElementList
-//		end-element()
-//
-// The top level rdf:RDF node. It can only have xmlns attributes, which have already been removed
-// during construction of the XML tree.
-
-static void
-RDF_RDF ( XMP_Node * xmpTree, const XML_Node & xmlNode )
-{
-
-	if ( ! xmlNode.attrs.empty() ) XMP_Throw ( "Invalid attributes of rdf:RDF element", kXMPErr_BadRDF );
-	RDF_NodeElementList ( xmpTree, xmlNode, kIsTopLevel );
-
-}	// RDF_RDF
-
-
-// =================================================================================================
-// RDF_NodeElementList
-// ===================
-//
-// 7.2.10 nodeElementList
-//		ws* ( nodeElement ws* )*
-
-static void
-RDF_NodeElementList ( XMP_Node * xmpParent, const XML_Node & xmlParent, bool isTopLevel )
-{
-	XMP_Assert ( isTopLevel );
-	
-	XML_cNodePos currChild = xmlParent.content.begin();	// *** Change these loops to the indexed pattern.
-	XML_cNodePos endChild  = xmlParent.content.end();
-
-	for ( ; currChild != endChild; ++currChild ) {
-		if ( (*currChild)->IsWhitespaceNode() ) continue;
-		RDF_NodeElement ( xmpParent, **currChild, isTopLevel );
-	}
-
-}	// RDF_NodeElementList
-
-
-// =================================================================================================
-// RDF_NodeElement
-// ===============
-//
-// 7.2.5 nodeElementURIs
-//		anyURI - ( coreSyntaxTerms | rdf:li | oldTerms )
-//
-// 7.2.11 nodeElement
-//		start-element ( URI == nodeElementURIs,
-//						attributes == set ( ( idAttr | nodeIdAttr | aboutAttr )?, propertyAttr* ) )
-//		propertyEltList
-//		end-element()
-//
-// A node element URI is rdf:Description or anything else that is not an RDF term.
-
-static void
-RDF_NodeElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel )
-{
-	RDFTermKind nodeTerm = GetRDFTermKind ( xmlNode.name );
-	if ( (nodeTerm != kRDFTerm_Description) && (nodeTerm != kRDFTerm_Other) ) {
-		XMP_Throw ( "Node element must be rdf:Description or typedNode", kXMPErr_BadRDF );
-	}
-
-	if ( isTopLevel && (nodeTerm == kRDFTerm_Other) ) {
-		XMP_Throw ( "Top level typedNode not allowed", kXMPErr_BadXMP );
-	} else {
-		RDF_NodeElementAttrs ( xmpParent, xmlNode, isTopLevel );
-		RDF_PropertyElementList ( xmpParent, xmlNode, isTopLevel );
-	}
-
-}	// RDF_NodeElement
-
-
-// =================================================================================================
-// RDF_NodeElementAttrs
-// ====================
-//
-// 7.2.7 propertyAttributeURIs
-//		anyURI - ( coreSyntaxTerms | rdf:Description | rdf:li | oldTerms )
-//
-// 7.2.11 nodeElement
-//		start-element ( URI == nodeElementURIs,
-//						attributes == set ( ( idAttr | nodeIdAttr | aboutAttr )?, propertyAttr* ) )
-//		propertyEltList
-//		end-element()
-//
-// Process the attribute list for an RDF node element. A property attribute URI is anything other
-// than an RDF term. The rdf:ID and rdf:nodeID attributes are simply ignored, as are rdf:about
-// attributes on inner nodes.
-
-static const XMP_OptionBits kExclusiveAttrMask = (kRDFMask_ID | kRDFMask_nodeID | kRDFMask_about);
-
-static void
-RDF_NodeElementAttrs ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel )
-{
-	XMP_OptionBits exclusiveAttrs = 0;	// Used to detect attributes that are mutually exclusive.
-
-	XML_cNodePos currAttr = xmlNode.attrs.begin();
-	XML_cNodePos endAttr  = xmlNode.attrs.end();
-
-	for ( ; currAttr != endAttr; ++currAttr ) {
-
-		RDFTermKind attrTerm = GetRDFTermKind ( (*currAttr)->name );
-
-		switch ( attrTerm ) {
-
-			case kRDFTerm_ID     :
-			case kRDFTerm_nodeID :
-			case kRDFTerm_about  :
-
-				if ( exclusiveAttrs & kExclusiveAttrMask ) XMP_Throw ( "Mutally exclusive about, ID, nodeID attributes", kXMPErr_BadRDF );
-				exclusiveAttrs |= (1 << attrTerm);
-
-				if ( isTopLevel && (attrTerm == kRDFTerm_about) ) {
-					// This is the rdf:about attribute on a top level node. Set the XMP tree name if
-					// it doesn't have a name yet. Make sure this name matches the XMP tree name.
-					XMP_Assert ( xmpParent->parent == 0 );	// Must be the tree root node.
-					if ( xmpParent->name.empty() ) {
-						xmpParent->name = (*currAttr)->value;
-					} else if ( ! (*currAttr)->value.empty() ) {
-						if ( xmpParent->name != (*currAttr)->value ) XMP_Throw ( "Mismatched top level rdf:about values", kXMPErr_BadXMP );
-					}
-				}
-
-				break;
-
-			case kRDFTerm_Other :
-				AddChildNode ( xmpParent, **currAttr, (*currAttr)->value.c_str(), isTopLevel );
-				break;
-
-			default :
-				XMP_Throw ( "Invalid nodeElement attribute", kXMPErr_BadRDF );
-
-		}
-
-	}
-
-}	// RDF_NodeElementAttrs
-
-
-// =================================================================================================
-// RDF_PropertyElementList
-// =======================
-//
-// 7.2.13 propertyEltList
-//		ws* ( propertyElt ws* )*
-
-static void
-RDF_PropertyElementList ( XMP_Node * xmpParent, const XML_Node & xmlParent, bool isTopLevel )
-{
-	XML_cNodePos currChild = xmlParent.content.begin();
-	XML_cNodePos endChild  = xmlParent.content.end();
-
-	for ( ; currChild != endChild; ++currChild ) {
-		if ( (*currChild)->IsWhitespaceNode() ) continue;
-		if ( (*currChild)->kind != kElemNode ) {
-			XMP_Throw ( "Expected property element node not found", kXMPErr_BadRDF );
-		}
-		RDF_PropertyElement ( xmpParent, **currChild, isTopLevel );
-	}
-
-}	// RDF_PropertyElementList
-
-
-// =================================================================================================
-// RDF_PropertyElement
-// ===================
-//
-// 7.2.14 propertyElt
-//		resourcePropertyElt | literalPropertyElt | parseTypeLiteralPropertyElt |
-//		parseTypeResourcePropertyElt | parseTypeCollectionPropertyElt | parseTypeOtherPropertyElt | emptyPropertyElt
-//
-// 7.2.15 resourcePropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr? ) )
-//		ws* nodeElement ws*
-//		end-element()
-//
-// 7.2.16 literalPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, datatypeAttr?) )
-//		text()
-//		end-element()
-//
-// 7.2.17 parseTypeLiteralPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseLiteral ) )
-//		literal
-//		end-element()
-//
-// 7.2.18 parseTypeResourcePropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseResource ) )
-//		propertyEltList
-//		end-element()
-//
-// 7.2.19 parseTypeCollectionPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseCollection ) )
-//		nodeElementList
-//		end-element()
-//
-// 7.2.20 parseTypeOtherPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseOther ) )
-//		propertyEltList
-//		end-element()
-//
-// 7.2.21 emptyPropertyElt
-//		start-element ( URI == propertyElementURIs,
-//						attributes == set ( idAttr?, ( resourceAttr | nodeIdAttr )?, propertyAttr* ) )
-//		end-element()
-//
-// The various property element forms are not distinguished by the XML element name, but by their
-// attributes for the most part. The exceptions are resourcePropertyElt and literalPropertyElt. They
-// are distinguished by their XML element content.
-//
-// NOTE: The RDF syntax does not explicitly include the xml:lang attribute although it can appear in
-// many of these. We have to allow for it in the attribute counts below.
-
-static void
-RDF_PropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel )
-{
-	RDFTermKind nodeTerm = GetRDFTermKind ( xmlNode.name );
-	if ( ! IsPropertyElementName ( nodeTerm ) ) XMP_Throw ( "Invalid property element name", kXMPErr_BadRDF );
-	
-	if ( xmlNode.attrs.size() > 3 ) {
-
-		// Only an emptyPropertyElt can have more than 3 attributes.
-		RDF_EmptyPropertyElement ( xmpParent, xmlNode, isTopLevel );
-
-	} else {
-
-		// Look through the attributes for one that isn't rdf:ID or xml:lang, it will usually tell
-		// what we should be dealing with. The called routines must verify their specific syntax!
-
-		XML_cNodePos currAttr = xmlNode.attrs.begin();
-		XML_cNodePos endAttr  = xmlNode.attrs.end();
-		XMP_VarString * attrName = 0;
-
-		for ( ; currAttr != endAttr; ++currAttr ) {
-			attrName = &((*currAttr)->name);
-			if ( (*attrName != "xml:lang") && (*attrName != "rdf:ID") ) break;
-		}
-
-		if ( currAttr != endAttr ) {
-
-			XMP_Assert ( attrName != 0 );
-			XMP_VarString& attrValue = (*currAttr)->value;
-
-			if ( *attrName == "rdf:datatype" ) {
-				RDF_LiteralPropertyElement ( xmpParent, xmlNode, isTopLevel );
-			} else if ( *attrName != "rdf:parseType" ) {
-				RDF_EmptyPropertyElement ( xmpParent, xmlNode, isTopLevel );
-			} else if ( attrValue == "Literal" ) {
-				RDF_ParseTypeLiteralPropertyElement ( xmpParent, xmlNode, isTopLevel );
-			} else if ( attrValue == "Resource" ) {
-				RDF_ParseTypeResourcePropertyElement ( xmpParent, xmlNode, isTopLevel );
-			} else if ( attrValue == "Collection" ) {
-				RDF_ParseTypeCollectionPropertyElement ( xmpParent, xmlNode, isTopLevel );
-			} else {
-				RDF_ParseTypeOtherPropertyElement ( xmpParent, xmlNode, isTopLevel );
-			}
-
-		} else {
-
-			// Only rdf:ID and xml:lang, could be a resourcePropertyElt, a literalPropertyElt, or an.
-			// emptyPropertyElt. Look at the child XML nodes to decide which.
-
-			if ( xmlNode.content.empty() ) {
-
-				RDF_EmptyPropertyElement ( xmpParent, xmlNode, isTopLevel );
-
-			} else {
-			
-				XML_cNodePos currChild = xmlNode.content.begin();
-				XML_cNodePos endChild  = xmlNode.content.end();
-
-				for ( ; currChild != endChild; ++currChild ) {
-					if ( (*currChild)->kind != kCDataNode ) break;
-				}
-				
-				if ( currChild == endChild ) {
-					RDF_LiteralPropertyElement ( xmpParent, xmlNode, isTopLevel );
-				} else {
-					RDF_ResourcePropertyElement ( xmpParent, xmlNode, isTopLevel );
-				}
-			
-			}
-
-		}
-		
-	}
-
-}	// RDF_PropertyElement
-
-
-// =================================================================================================
-// RDF_ResourcePropertyElement
-// ===========================
-//
-// 7.2.15 resourcePropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr? ) )
-//		ws* nodeElement ws*
-//		end-element()
-//
-// This handles structs using an rdf:Description node, arrays using rdf:Bag/Seq/Alt, and typedNodes.
-// It also catches and cleans up qualified properties written with rdf:Description and rdf:value.
-
-static void
-RDF_ResourcePropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel )
-{
-	if ( isTopLevel && (xmlNode.name == "iX:changes") ) return;	// Strip old "punchcard" chaff.
-	
-	XMP_Node * newCompound = AddChildNode ( xmpParent, xmlNode, "", isTopLevel );
-	
-	XML_cNodePos currAttr = xmlNode.attrs.begin();
-	XML_cNodePos endAttr  = xmlNode.attrs.end();
-
-	for ( ; currAttr != endAttr; ++currAttr ) {
-		XMP_VarString & attrName = (*currAttr)->name;
-		if ( attrName == "xml:lang" ) {
-			AddQualifierNode ( newCompound, **currAttr );
-		} else if ( attrName == "rdf:ID" ) {
-			continue;	// Ignore all rdf:ID attributes.
-		} else {
-			XMP_Throw ( "Invalid attribute for resource property element", kXMPErr_BadRDF );
-		}
-	}
-	
-	XML_cNodePos currChild = xmlNode.content.begin();
-	XML_cNodePos endChild  = xmlNode.content.end();
-
-	for ( ; currChild != endChild; ++currChild ) {
-		if ( ! (*currChild)->IsWhitespaceNode() ) break;
-	}
-	if ( currChild == endChild ) XMP_Throw ( "Missing child of resource property element", kXMPErr_BadRDF );
-	if ( (*currChild)->kind != kElemNode ) XMP_Throw ( "Children of resource property element must be XML elements", kXMPErr_BadRDF );
-
-	if ( (*currChild)->name == "rdf:Bag" ) {
-		newCompound->options |= kXMP_PropValueIsArray;
-	} else if ( (*currChild)->name == "rdf:Seq" ) {
-		newCompound->options |= kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered;
-	} else if ( (*currChild)->name == "rdf:Alt" ) {
-		newCompound->options |= kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate;
-	} else {
-		newCompound->options |= kXMP_PropValueIsStruct;
-		if ( (*currChild)->name != "rdf:Description" ) {
-			XMP_VarString typeName ( (*currChild)->ns );
-			size_t        colonPos = (*currChild)->name.find_first_of(':');
-			if ( colonPos == XMP_VarString::npos ) XMP_Throw ( "All XML elements must be in a namespace", kXMPErr_BadXMP );
-			typeName.append ( (*currChild)->name, colonPos, XMP_VarString::npos );
-			AddQualifierNode ( newCompound, XMP_VarString("rdf:type"), typeName );
-		}
-	}
-
-	RDF_NodeElement ( newCompound, **currChild, kNotTopLevel );
-	if ( newCompound->options & kRDF_HasValueElem ) {
-		FixupQualifiedNode ( newCompound );
-	} else if ( newCompound->options & kXMP_PropArrayIsAlternate ) {
-		DetectAltText ( newCompound );
-	}
-
-	for ( ++currChild; currChild != endChild; ++currChild ) {
-		if ( ! (*currChild)->IsWhitespaceNode() ) XMP_Throw ( "Invalid child of resource property element", kXMPErr_BadRDF );
-	}
-
-}	// RDF_ResourcePropertyElement
-
-
-// =================================================================================================
-// RDF_LiteralPropertyElement
-// ==========================
-//
-// 7.2.16 literalPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, datatypeAttr?) )
-//		text()
-//		end-element()
-//
-// Add a leaf node with the text value and qualifiers for the attributes.
-
-static void
-RDF_LiteralPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel )
-{
-	XMP_Node * newChild = AddChildNode ( xmpParent, xmlNode, "", isTopLevel );
-	
-	XML_cNodePos currAttr = xmlNode.attrs.begin();
-	XML_cNodePos endAttr  = xmlNode.attrs.end();
-
-	for ( ; currAttr != endAttr; ++currAttr ) {
-		XMP_VarString & attrName = (*currAttr)->name;
-		if ( attrName == "xml:lang" ) {
-			AddQualifierNode ( newChild, **currAttr );
-		} else if ( (attrName == "rdf:ID") || (attrName == "rdf:datatype") ) {
-			continue;	// Ignore all rdf:ID and rdf:datatype attributes.
-		} else {
-			XMP_Throw ( "Invalid attribute for literal property element", kXMPErr_BadRDF );
-		}
-	}
-	
-	XML_cNodePos currChild = xmlNode.content.begin();
-	XML_cNodePos endChild  = xmlNode.content.end();
-	size_t      textSize  = 0;
-
-	for ( ; currChild != endChild; ++currChild ) {
-		if ( (*currChild)->kind != kCDataNode ) XMP_Throw ( "Invalid child of literal property element", kXMPErr_BadRDF );
-		textSize += (*currChild)->value.size();
-	}
-	
-	newChild->value.reserve ( textSize );
-
-	for ( currChild = xmlNode.content.begin(); currChild != endChild; ++currChild ) {
-		newChild->value += (*currChild)->value;
-	}
-
-	#if 0	// *** XMP_DebugBuild
-		newChild->_valuePtr = newChild->value.c_str();
-	#endif
-	
-}	// RDF_LiteralPropertyElement
-
-
-// =================================================================================================
-// RDF_ParseTypeLiteralPropertyElement
-// ===================================
-//
-// 7.2.17 parseTypeLiteralPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseLiteral ) )
-//		literal
-//		end-element()
-
-static void
-RDF_ParseTypeLiteralPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel )
-{
-	IgnoreParam(xmpParent); IgnoreParam(xmlNode); IgnoreParam(isTopLevel); 
-	
-	XMP_Throw ( "ParseTypeLiteral property element not allowed", kXMPErr_BadXMP );
-
-}	// RDF_ParseTypeLiteralPropertyElement
-
-
-// =================================================================================================
-// RDF_ParseTypeResourcePropertyElement
-// ====================================
-//
-// 7.2.18 parseTypeResourcePropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseResource ) )
-//		propertyEltList
-//		end-element()
-//
-// Add a new struct node with a qualifier for the possible rdf:ID attribute. Then process the XML
-// child nodes to get the struct fields.
-
-static void
-RDF_ParseTypeResourcePropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel )
-{
-
-	XMP_Node * newStruct = AddChildNode ( xmpParent, xmlNode, "", isTopLevel );
-	newStruct->options  |= kXMP_PropValueIsStruct;
-	
-	XML_cNodePos currAttr = xmlNode.attrs.begin();
-	XML_cNodePos endAttr  = xmlNode.attrs.end();
-
-	for ( ; currAttr != endAttr; ++currAttr ) {
-		XMP_VarString & attrName = (*currAttr)->name;
-		if ( attrName == "rdf:parseType" ) {
-			continue;	// ! The caller ensured the value is "Resource".
-		} else if ( attrName == "xml:lang" ) {
-			AddQualifierNode ( newStruct, **currAttr );
-		} else if ( attrName == "rdf:ID" ) {
-			continue;	// Ignore all rdf:ID attributes.
-		} else {
-			XMP_Throw ( "Invalid attribute for ParseTypeResource property element", kXMPErr_BadRDF );
-		}
-	}
-
-	RDF_PropertyElementList ( newStruct, xmlNode, kNotTopLevel );
-
-	if ( newStruct->options & kRDF_HasValueElem ) FixupQualifiedNode ( newStruct );
-	
-	// *** Need to look for arrays using rdf:Description and rdf:type.
-
-}	// RDF_ParseTypeResourcePropertyElement
-
-
-// =================================================================================================
-// RDF_ParseTypeCollectionPropertyElement
-// ======================================
-//
-// 7.2.19 parseTypeCollectionPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseCollection ) )
-//		nodeElementList
-//		end-element()
-
-static void
-RDF_ParseTypeCollectionPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel )
-{
-	IgnoreParam(xmpParent); IgnoreParam(xmlNode); IgnoreParam(isTopLevel); 
-
-	XMP_Throw ( "ParseTypeCollection property element not allowed", kXMPErr_BadXMP );
-
-}	// RDF_ParseTypeCollectionPropertyElement
-
-
-// =================================================================================================
-// RDF_ParseTypeOtherPropertyElement
-// =================================
-//
-// 7.2.20 parseTypeOtherPropertyElt
-//		start-element ( URI == propertyElementURIs, attributes == set ( idAttr?, parseOther ) )
-//		propertyEltList
-//		end-element()
-
-static void
-RDF_ParseTypeOtherPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel )
-{
-	IgnoreParam(xmpParent); IgnoreParam(xmlNode); IgnoreParam(isTopLevel); 
-
-	XMP_Throw ( "ParseTypeOther property element not allowed", kXMPErr_BadXMP );
-
-}	// RDF_ParseTypeOtherPropertyElement
-
-
-// =================================================================================================
-// RDF_EmptyPropertyElement
-// ========================
-//
-// 7.2.21 emptyPropertyElt
-//		start-element ( URI == propertyElementURIs,
-//						attributes == set ( idAttr?, ( resourceAttr | nodeIdAttr )?, propertyAttr* ) )
-//		end-element()
-//
-//	<ns:Prop1/>  <!-- a simple property with an empty value --> 
-//	<ns:Prop2 rdf:resource="http://www.adobe.com/"/> <!-- a URI value --> 
-//	<ns:Prop3 rdf:value="..." ns:Qual="..."/> <!-- a simple qualified property --> 
-//	<ns:Prop4 ns:Field1="..." ns:Field2="..."/> <!-- a struct with simple fields -->
-//
-// An emptyPropertyElt is an element with no contained content, just a possibly empty set of
-// attributes. An emptyPropertyElt can represent three special cases of simple XMP properties: a
-// simple property with an empty value (ns:Prop1), a simple property whose value is a URI
-// (ns:Prop2), or a simple property with simple qualifiers (ns:Prop3). An emptyPropertyElt can also
-// represent an XMP struct whose fields are all simple and unqualified (ns:Prop4).
-//
-// It is an error to use both rdf:value and rdf:resource - that can lead to invalid  RDF in the
-// verbose form written using a literalPropertyElt.
-//
-// The XMP mapping for an emptyPropertyElt is a bit different from generic RDF, partly for 
-// design reasons and partly for historical reasons. The XMP mapping rules are: 
-//	1. If there is an rdf:value attribute then this is a simple property with a text value.
-//		All other attributes are qualifiers.
-//	2. If there is an rdf:resource attribute then this is a simple property with a URI value. 
-//		All other attributes are qualifiers.
-//	3. If there are no attributes other than xml:lang, rdf:ID, or rdf:nodeID then this is a simple 
-//		property with an empty value. 
-//	4. Otherwise this is a struct, the attributes other than xml:lang, rdf:ID, or rdf:nodeID are fields. 
-
-static void
-RDF_EmptyPropertyElement ( XMP_Node * xmpParent, const XML_Node & xmlNode, bool isTopLevel )
-{
-	bool hasPropertyAttrs = false;
-	bool hasResourceAttr  = false;
-	bool hasNodeIDAttr    = false;
-	bool hasValueAttr     = false;
-	
-	const XML_Node * valueNode = 0;	// ! Can come from rdf:value or rdf:resource.
-	
-	if ( ! xmlNode.content.empty() ) XMP_Throw ( "Nested content not allowed with rdf:resource or property attributes", kXMPErr_BadRDF );
-	
-	// First figure out what XMP this maps to and remember the XML node for a simple value.
-	
-	XML_cNodePos currAttr = xmlNode.attrs.begin();
-	XML_cNodePos endAttr  = xmlNode.attrs.end();
-
-	for ( ; currAttr != endAttr; ++currAttr ) {
-
-		RDFTermKind attrTerm = GetRDFTermKind ( (*currAttr)->name );
-
-		switch ( attrTerm ) {
-
-			case kRDFTerm_ID :
-				// Nothing to do.
-				break;
-
-			case kRDFTerm_resource :
-				if ( hasNodeIDAttr ) XMP_Throw ( "Empty property element can't have both rdf:resource and rdf:nodeID", kXMPErr_BadRDF );
-				if ( hasValueAttr ) XMP_Throw ( "Empty property element can't have both rdf:value and rdf:resource", kXMPErr_BadXMP );
-				hasResourceAttr = true;
-				if ( ! hasValueAttr ) valueNode = *currAttr;
-				break;
-
-			case kRDFTerm_nodeID :
-				if ( hasResourceAttr ) XMP_Throw ( "Empty property element can't have both rdf:resource and rdf:nodeID", kXMPErr_BadRDF );
-				hasNodeIDAttr = true;
-				break;
-
-			case kRDFTerm_Other :
-				if ( (*currAttr)->name == "rdf:value" ) {
-					if ( hasResourceAttr ) XMP_Throw ( "Empty property element can't have both rdf:value and rdf:resource", kXMPErr_BadXMP );
-					hasValueAttr = true;
-					valueNode = *currAttr;
-				} else if ( (*currAttr)->name != "xml:lang" ) {
-					hasPropertyAttrs = true;
-				}
-				break;
-
-			default :
-				XMP_Throw ( "Unrecognized attribute of empty property element", kXMPErr_BadRDF );
-				break;
-
-		}
-
-	}
-	
-	// Create the right kind of child node and visit the attributes again to add the fields or qualifiers.
-	// ! Because of implementation vagaries, the xmpParent is the tree root for top level properties.
-	// ! The schema is found, created if necessary, by AddChildNode.
-	
-	XMP_Node * childNode = AddChildNode ( xmpParent, xmlNode, "", isTopLevel );
-	bool childIsStruct = false;
-	
-	if ( hasValueAttr | hasResourceAttr ) {
-		childNode->value = valueNode->value;
-		if ( ! hasValueAttr ) childNode->options |= kXMP_PropValueIsURI;	// ! Might have both rdf:value and rdf:resource.
-	} else if ( hasPropertyAttrs ) {
-		childNode->options |= kXMP_PropValueIsStruct;
-		childIsStruct = true;
-	}
-		
-	currAttr = xmlNode.attrs.begin();
-	endAttr  = xmlNode.attrs.end();
-
-	for ( ; currAttr != endAttr; ++currAttr ) {
-
-		if ( *currAttr == valueNode ) continue;	// Skip the rdf:value or rdf:resource attribute holding the value.
-		RDFTermKind attrTerm = GetRDFTermKind ( (*currAttr)->name );
-
-		switch ( attrTerm ) {
-
-			case kRDFTerm_ID       :
-			case kRDFTerm_nodeID   :
-				break;	// Ignore all rdf:ID and rdf:nodeID attributes.w
-				
-			case kRDFTerm_resource :
-				AddQualifierNode ( childNode, **currAttr );
-				break;
-
-			case kRDFTerm_Other :
-				if ( (! childIsStruct) || (*currAttr)->name == "xml:lang" ) {
-					AddQualifierNode ( childNode, **currAttr );
-				} else {
-					AddChildNode ( childNode, **currAttr, (*currAttr)->value.c_str(), false );
-				}
-				break;
-
-			default :
-				XMP_Throw ( "Unrecognized attribute of empty property element", kXMPErr_BadRDF );
-				break;
-
-		}
-
-	}
-
-}	// RDF_EmptyPropertyElement
-
-
-// =================================================================================================
diff --git a/xmpsdk/src/UnicodeConversions.cpp b/xmpsdk/src/UnicodeConversions.cpp
deleted file mode 100644
index 123c502b..00000000
--- a/xmpsdk/src/UnicodeConversions.cpp
+++ /dev/null
@@ -1,1665 +0,0 @@
-// =================================================================================================
-// Copyright 2004-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Const.h"
-
-#if UnicodeTestBuild
-	#include <cassert>
-	#include <stdexcept>
-	#define UC_Assert assert
-	#define UC_Throw(m,k) throw std::logic_error ( m )
-#else
-	#define UC_Assert(cond) /* Nothing for now, should be XMP_Assert. */
-	#define UC_Throw(msg,id)  throw XMP_Error ( id, msg )
-#endif
-
-#include "UnicodeConversions.hpp"
-
-using namespace std;
-
-// =================================================================================================
-
-// *** Look into using asm inlines, e.g. count-leading bits for multi-byte UTF-8.
-
-CodePoint_to_UTF16_Proc CodePoint_to_UTF16BE = 0;
-CodePoint_to_UTF16_Proc CodePoint_to_UTF16LE = 0;
-
-CodePoint_from_UTF16_Proc CodePoint_from_UTF16BE = 0;
-CodePoint_from_UTF16_Proc CodePoint_from_UTF16LE = 0;
-
-UTF8_to_UTF16_Proc  UTF8_to_UTF16BE = 0;
-UTF8_to_UTF16_Proc  UTF8_to_UTF16LE = 0;
-UTF8_to_UTF32_Proc  UTF8_to_UTF32BE = 0;
-UTF8_to_UTF32_Proc  UTF8_to_UTF32LE = 0;
-
-UTF16_to_UTF8_Proc  UTF16BE_to_UTF8 = 0;
-UTF16_to_UTF8_Proc  UTF16LE_to_UTF8 = 0;
-UTF32_to_UTF8_Proc  UTF32BE_to_UTF8 = 0;
-UTF32_to_UTF8_Proc  UTF32LE_to_UTF8 = 0;
-
-UTF8_to_UTF16_Proc  UTF8_to_UTF16Native = 0;
-UTF8_to_UTF32_Proc  UTF8_to_UTF32Native = 0;
-UTF16_to_UTF8_Proc  UTF16Native_to_UTF8 = 0;
-UTF32_to_UTF8_Proc  UTF32Native_to_UTF8 = 0;
-
-UTF16_to_UTF32_Proc UTF16BE_to_UTF32BE = 0;
-UTF16_to_UTF32_Proc UTF16BE_to_UTF32LE = 0;
-UTF16_to_UTF32_Proc UTF16LE_to_UTF32BE = 0;
-UTF16_to_UTF32_Proc UTF16LE_to_UTF32LE = 0;
-
-UTF32_to_UTF16_Proc UTF32BE_to_UTF16BE = 0;
-UTF32_to_UTF16_Proc UTF32BE_to_UTF16LE = 0;
-UTF32_to_UTF16_Proc UTF32LE_to_UTF16BE = 0;
-UTF32_to_UTF16_Proc UTF32LE_to_UTF16LE = 0;
-
-// -------------------------------------------------------------------------------------------------
-
-static size_t swap32to16Offset = 0;	// Offset to "convert" a swapped UTF32 pointer into a swapped UTF16 pointer.
-
-// -------------------------------------------------------------------------------------------------
-
-static void CodePoint_to_UTF16Nat ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written );
-static void CodePoint_to_UTF16Swp ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written );
-
-static void CodePoint_from_UTF16Nat ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read );
-static void CodePoint_from_UTF16Swp ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read );
-
-// -------------------------------------------------------------------------------------------------
-
-static void UTF8_to_UTF16Nat ( const UTF8Unit *  utf8In,    const size_t utf8Len,
-				               UTF16Unit *       utf16Out,  const size_t utf16Len,
-				               size_t *          utf8Read,  size_t *     utf16Written );
-
-static void UTF8_to_UTF16Swp ( const UTF8Unit *  utf8In,    const size_t utf8Len,
-				               UTF16Unit *       utf16Out,  const size_t utf16Len,
-				               size_t *          utf8Read,  size_t *     utf16Written );
-
-static void UTF8_to_UTF32Nat ( const UTF8Unit *  utf8In,    const size_t utf8Len,
-				               UTF32Unit *       utf32Out,  const size_t utf32Len,
-				               size_t *          utf8Read,  size_t *     utf32Written );
-
-static void UTF8_to_UTF32Swp ( const UTF8Unit *  utf8In,    const size_t utf8Len,
-				               UTF32Unit *       utf32Out,  const size_t utf32Len,
-				               size_t *          utf8Read,  size_t *     utf32Written );
-
-// -------------------------------------------------------------------------------------------------
-
-static void UTF16Nat_to_UTF8 ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				               UTF8Unit *        utf8Out,   const size_t utf8Len,
-				               size_t *          utf16Read, size_t *     utf8Written );
-
-static void UTF16Swp_to_UTF8 ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				               UTF8Unit *        utf8Out,   const size_t utf8Len,
-				               size_t *          utf16Read, size_t *     utf8Written );
-
-static void UTF32Nat_to_UTF8 ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				               UTF8Unit *        utf8Out,   const size_t utf8Len,
-				               size_t *          utf32Read, size_t *     utf8Written );
-
-static void UTF32Swp_to_UTF8 ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				               UTF8Unit *        utf8Out,   const size_t utf8Len,
-				               size_t *          utf32Read, size_t *     utf8Written );
-
-// -------------------------------------------------------------------------------------------------
-
-static void UTF16Nat_to_UTF32Nat ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				                   UTF32Unit *       utf32Out,  const size_t utf32Len,
-				                   size_t *          utf16Read, size_t *     utf32Written );
-
-static void UTF16Nat_to_UTF32Swp ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				                   UTF32Unit *       utf32Out,  const size_t utf32Len,
-				                   size_t *          utf16Read, size_t *     utf32Written );
-
-static void UTF16Swp_to_UTF32Nat ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				                   UTF32Unit *       utf32Out,  const size_t utf32Len,
-				                   size_t *          utf16Read, size_t *     utf32Written );
-
-static void UTF16Swp_to_UTF32Swp ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				                   UTF32Unit *       utf32Out,  const size_t utf32Len,
-				                   size_t *          utf16Read, size_t *     utf32Written );
-
-// -------------------------------------------------------------------------------------------------
-
-static void UTF32Nat_to_UTF16Nat ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				                   UTF16Unit *       utf16Out,  const size_t utf16Len,
-				                   size_t *          utf32Read, size_t *     utf16Written );
-
-static void UTF32Nat_to_UTF16Swp ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				                   UTF16Unit *       utf16Out,  const size_t utf16Len,
-				                   size_t *          utf32Read, size_t *     utf16Written );
-
-static void UTF32Swp_to_UTF16Nat ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				                   UTF16Unit *       utf16Out,  const size_t utf16Len,
-				                   size_t *          utf32Read, size_t *     utf16Written );
-
-static void UTF32Swp_to_UTF16Swp ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				                   UTF16Unit *       utf16Out,  const size_t utf16Len,
-				                   size_t *          utf32Read, size_t *     utf16Written );
-
-// =================================================================================================
-
-void InitializeUnicodeConversions()
-{
-	UC_Assert ( (sizeof(UTF8Unit) == 1) && (sizeof(UTF16Unit) == 2) && (sizeof(UTF32Unit) == 4) ); 
-
-	UTF16Unit u16  = 0x00FF;
-	bool bigEndian = (*((UTF8Unit*)&u16) == 0);
-
-	UTF8_to_UTF16Native = UTF8_to_UTF16Nat;
-	UTF8_to_UTF32Native = UTF8_to_UTF32Nat;
-	UTF16Native_to_UTF8 = UTF16Nat_to_UTF8;
-	UTF32Native_to_UTF8 = UTF32Nat_to_UTF8;
-	
-	if ( bigEndian ) {
-	
-		swap32to16Offset = 0;
-
-		CodePoint_to_UTF16BE = CodePoint_to_UTF16Nat;
-		CodePoint_to_UTF16LE = CodePoint_to_UTF16Swp;
-
-		CodePoint_from_UTF16BE = CodePoint_from_UTF16Nat;
-		CodePoint_from_UTF16LE = CodePoint_from_UTF16Swp;
-
-		UTF8_to_UTF16BE = UTF8_to_UTF16Nat;
-		UTF8_to_UTF16LE = UTF8_to_UTF16Swp;
-		UTF8_to_UTF32BE = UTF8_to_UTF32Nat;
-		UTF8_to_UTF32LE = UTF8_to_UTF32Swp;
-
-		UTF16BE_to_UTF8 = UTF16Nat_to_UTF8;
-		UTF16LE_to_UTF8 = UTF16Swp_to_UTF8;
-		UTF32BE_to_UTF8 = UTF32Nat_to_UTF8;
-		UTF32LE_to_UTF8 = UTF32Swp_to_UTF8;
-
-		UTF16BE_to_UTF32BE = UTF16Nat_to_UTF32Nat;
-		UTF16BE_to_UTF32LE = UTF16Nat_to_UTF32Swp;
-		UTF16LE_to_UTF32BE = UTF16Swp_to_UTF32Nat;
-		UTF16LE_to_UTF32LE = UTF16Swp_to_UTF32Swp;
-
-		UTF32BE_to_UTF16BE = UTF32Nat_to_UTF16Nat;
-		UTF32BE_to_UTF16LE = UTF32Nat_to_UTF16Swp;
-		UTF32LE_to_UTF16BE = UTF32Swp_to_UTF16Nat;
-		UTF32LE_to_UTF16LE = UTF32Swp_to_UTF16Swp;
-
-	} else {
-	
-		swap32to16Offset = 1;	// ! Offset in UTF16 units!
-
-		CodePoint_to_UTF16BE = CodePoint_to_UTF16Swp;
-		CodePoint_to_UTF16LE = CodePoint_to_UTF16Nat;
-
-		CodePoint_from_UTF16BE = CodePoint_from_UTF16Swp;
-		CodePoint_from_UTF16LE = CodePoint_from_UTF16Nat;
-
-		UTF8_to_UTF16BE = UTF8_to_UTF16Swp;
-		UTF8_to_UTF16LE = UTF8_to_UTF16Nat;
-		UTF8_to_UTF32BE = UTF8_to_UTF32Swp;
-		UTF8_to_UTF32LE = UTF8_to_UTF32Nat;
-
-		UTF16BE_to_UTF8 = UTF16Swp_to_UTF8;
-		UTF16LE_to_UTF8 = UTF16Nat_to_UTF8;
-		UTF32BE_to_UTF8 = UTF32Swp_to_UTF8;
-		UTF32LE_to_UTF8 = UTF32Nat_to_UTF8;
-
-		UTF16BE_to_UTF32BE = UTF16Swp_to_UTF32Swp;
-		UTF16BE_to_UTF32LE = UTF16Swp_to_UTF32Nat;
-		UTF16LE_to_UTF32BE = UTF16Nat_to_UTF32Swp;
-		UTF16LE_to_UTF32LE = UTF16Nat_to_UTF32Nat;
-
-		UTF32BE_to_UTF16BE = UTF32Swp_to_UTF16Swp;
-		UTF32BE_to_UTF16LE = UTF32Swp_to_UTF16Nat;
-		UTF32LE_to_UTF16BE = UTF32Nat_to_UTF16Swp;
-		UTF32LE_to_UTF16LE = UTF32Nat_to_UTF16Nat;
-
-	}
-
-}	// InitializeUnicodeConversions
-
-// =================================================================================================
-
-#if XMP_MacBuild && __MWERKS__ 
-
-	#define UTF16InSwap(inPtr)	UTF16Unit ( __lhbrx ( (void*)(inPtr), 0 ) )
-	#define UTF32InSwap(inPtr)	UTF32Unit ( __lwbrx ( (void*)(inPtr), 0 ) )
-	
-	#define UTF16OutSwap(outPtr,value)	__sthbrx ( value, (void*)(outPtr), 0 )
-	#define UTF32OutSwap(outPtr,value)	__stwbrx ( value, (void*)(outPtr), 0 )
-
-#else
-
-	static inline UTF16Unit UTF16InSwap ( const UTF16Unit * inPtr )
-	{
-		UTF16Unit inUnit = *inPtr;
-		return (inUnit << 8) | (inUnit >> 8);
-	}
-
-	static inline UTF32Unit UTF32InSwap ( const UTF32Unit * inPtr )
-	{
-		UTF32Unit inUnit = *inPtr;
-		return (inUnit << 24) | ((inUnit << 8) & 0x00FF0000) | ((inUnit >> 8) & 0x0000FF00) | (inUnit >> 24);
-	}
-
-	static inline void UTF16OutSwap ( UTF16Unit * outPtr, const UTF16Unit value )
-	{
-		UTF16Unit outUnit = (value << 8) | (value >> 8);
-		*outPtr = outUnit;
-	}
-
-	static inline void UTF32OutSwap ( UTF32Unit * outPtr, const UTF32Unit value )
-	{
-		UTF32Unit outUnit = (value << 24) | ((value << 8) & 0x00FF0000) | ((value >> 8) & 0x0000FF00) | (value >> 24);
-		*outPtr = outUnit;
-	}
-
-#endif
-
-// =================================================================================================
-
-void SwapUTF16 ( const UTF16Unit * utf16In, UTF16Unit * utf16Out, const size_t utf16Len )
-{
-	for ( size_t i = 0; i < utf16Len; ++i ) utf16Out[i] = UTF16InSwap(utf16In+i);
-}
-
-void SwapUTF32 ( const UTF32Unit * utf32In, UTF32Unit * utf32Out, const size_t utf32Len ) {
-	for ( size_t i = 0; i < utf32Len; ++i ) utf32Out[i] = UTF32InSwap(utf32In+i);
-}
-
-// =================================================================================================
-
-extern void ToUTF16 ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf16Str, bool bigEndian )
-{
-	UTF8_to_UTF16_Proc Converter = UTF8_to_UTF16LE;
-	if ( bigEndian ) Converter = UTF8_to_UTF16BE;
-	
-	enum { kBufferSize = 8*1024 };
-	UTF16Unit u16Buffer[kBufferSize];	// 16K bytes
-	size_t readCount, writeCount;
-
-	utf16Str->erase();
-	utf16Str->reserve ( 2*utf8Len );	// As good a guess as any.
-	
-	while ( utf8Len > 0 ) {
-		Converter ( utf8In, utf8Len, u16Buffer, kBufferSize, &readCount, &writeCount );
-		if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML );
-		utf16Str->append ( (const char *)u16Buffer, writeCount*2 );
-		utf8In  += readCount;
-		utf8Len -= readCount;
-	}
-
-}	// ToUTF16
-
-// =================================================================================================
-
-extern void ToUTF16Native ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf16Str )
-{
-	enum { kBufferSize = 8*1024 };
-	UTF16Unit u16Buffer[kBufferSize];	// 16K bytes
-	size_t readCount, writeCount;
-
-	utf16Str->erase();
-	utf16Str->reserve ( 2*utf8Len );	// As good a guess as any.
-	
-	while ( utf8Len > 0 ) {
-		UTF8_to_UTF16Nat ( utf8In, utf8Len, u16Buffer, kBufferSize, &readCount, &writeCount );
-		if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML );
-		utf16Str->append ( (const char *)u16Buffer, writeCount*2 );
-		utf8In  += readCount;
-		utf8Len -= readCount;
-	}
-
-}	// ToUTF16Native
-
-// =================================================================================================
-
-extern void ToUTF32 ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf32Str, bool bigEndian )
-{
-	UTF8_to_UTF32_Proc Converter = UTF8_to_UTF32LE;
-	if ( bigEndian ) Converter = UTF8_to_UTF32BE;
-	
-	enum { kBufferSize = 4*1024 };
-	UTF32Unit u32Buffer[kBufferSize];	// 16K bytes
-	size_t readCount, writeCount;
-
-	utf32Str->erase();
-	utf32Str->reserve ( 4*utf8Len );	// As good a guess as any.
-	
-	while ( utf8Len > 0 ) {
-		Converter ( utf8In, utf8Len, u32Buffer, kBufferSize, &readCount, &writeCount );
-		if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML );
-		utf32Str->append ( (const char *)u32Buffer, writeCount*4 );
-		utf8In  += readCount;
-		utf8Len -= readCount;
-	}
-
-}	// ToUTF32
-
-// =================================================================================================
-
-extern void ToUTF32Native ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf32Str )
-{
-	enum { kBufferSize = 4*1024 };
-	UTF32Unit u32Buffer[kBufferSize];	// 16K bytes
-	size_t readCount, writeCount;
-
-	utf32Str->erase();
-	utf32Str->reserve ( 4*utf8Len );	// As good a guess as any.
-	
-	while ( utf8Len > 0 ) {
-		UTF8_to_UTF32Nat ( utf8In, utf8Len, u32Buffer, kBufferSize, &readCount, &writeCount );
-		if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML );
-		utf32Str->append ( (const char *)u32Buffer, writeCount*4 );
-		utf8In  += readCount;
-		utf8Len -= readCount;
-	}
-
-}	// ToUTF32Native
-
-// =================================================================================================
-
-extern void FromUTF16 ( const UTF16Unit * utf16In, size_t utf16Len, std::string * utf8Str, bool bigEndian )
-{
-	UTF16_to_UTF8_Proc Converter = UTF16LE_to_UTF8;
-	if ( bigEndian ) Converter = UTF16BE_to_UTF8;
-	
-	enum { kBufferSize = 16*1024 };
-	UTF8Unit u8Buffer[kBufferSize];
-	size_t readCount, writeCount;
-
-	utf8Str->erase();
-	utf8Str->reserve ( 2*utf16Len );	// As good a guess as any.
-	
-	while ( utf16Len > 0 ) {
-		Converter ( utf16In, utf16Len, u8Buffer, kBufferSize, &readCount, &writeCount );
-		if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML );
-		utf8Str->append ( (const char *)u8Buffer, writeCount );
-		utf16In  += readCount;
-		utf16Len -= readCount;
-	}
-
-}	// FromUTF16
-
-// =================================================================================================
-
-extern void FromUTF16Native ( const UTF16Unit * utf16In, size_t utf16Len, std::string * utf8Str )
-{
-	enum { kBufferSize = 16*1024 };
-	UTF8Unit u8Buffer[kBufferSize];
-	size_t readCount, writeCount;
-
-	utf8Str->erase();
-	utf8Str->reserve ( 2*utf16Len );	// As good a guess as any.
-	
-	while ( utf16Len > 0 ) {
-		UTF16Nat_to_UTF8 ( utf16In, utf16Len, u8Buffer, kBufferSize, &readCount, &writeCount );
-		if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML );
-		utf8Str->append ( (const char *)u8Buffer, writeCount );
-		utf16In  += readCount;
-		utf16Len -= readCount;
-	}
-
-}	// FromUTF16Native
-
-// =================================================================================================
-
-extern void FromUTF32 ( const UTF32Unit * utf32In, size_t utf32Len, std::string * utf8Str, bool bigEndian )
-{
-	UTF32_to_UTF8_Proc Converter = UTF32LE_to_UTF8;
-	if ( bigEndian ) Converter = UTF32BE_to_UTF8;
-	
-	enum { kBufferSize = 16*1024 };
-	UTF8Unit u8Buffer[kBufferSize];
-	size_t readCount, writeCount;
-
-	utf8Str->erase();
-	utf8Str->reserve ( 2*utf32Len );	// As good a guess as any.
-	
-	while ( utf32Len > 0 ) {
-		Converter ( utf32In, utf32Len, u8Buffer, kBufferSize, &readCount, &writeCount );
-		if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML );
-		utf8Str->append ( (const char *)u8Buffer, writeCount );
-		utf32In  += readCount;
-		utf32Len -= readCount;
-	}
-
-}	// FromUTF32
-
-// =================================================================================================
-
-extern void FromUTF32Native ( const UTF32Unit * utf32In, size_t utf32Len, std::string * utf8Str )
-{
-	enum { kBufferSize = 16*1024 };
-	UTF8Unit u8Buffer[kBufferSize];
-	size_t readCount, writeCount;
-
-	utf8Str->erase();
-	utf8Str->reserve ( 2*utf32Len );	// As good a guess as any.
-	
-	while ( utf32Len > 0 ) {
-		UTF32Nat_to_UTF8 ( utf32In, utf32Len, u8Buffer, kBufferSize, &readCount, &writeCount );
-		if ( writeCount == 0 ) UC_Throw ( "Incomplete Unicode at end of string", kXMPErr_BadXML );
-		utf8Str->append ( (const char *)u8Buffer, writeCount );
-		utf32In  += readCount;
-		utf32Len -= readCount;
-	}
-
-}	// FromUTF32Native
-
-// =================================================================================================
-
-static void CodePoint_to_UTF8_Multi ( const UTF32Unit cpIn, UTF8Unit * utf8Out, const size_t utf8Len, size_t * utf8Written )
-{
-	size_t unitCount = 0;
-	
-	if ( cpIn > 0x10FFFF ) UC_Throw ( "Bad UTF-32 - out of range", kXMPErr_BadParam );
-	if ( (0xD800 <= cpIn) && (cpIn <= 0xDFFF) ) UC_Throw ( "Bad UTF-32 - surrogate code point", kXMPErr_BadParam );
-	
-	// Compute the number of bytes using 6 data bits each. Then see if the highest order bits will
-	// fit into the leading byte. Write the UTF-8 sequence if there is enough room.
-	
-	UTF32Unit temp, mask;
-	size_t bytesNeeded = 0;
-	for ( temp = cpIn; temp != 0; temp = temp >> 6 ) ++bytesNeeded;
-	
-	temp = cpIn >> ((bytesNeeded-1)*6);	// The highest order data bits.
-	mask = (0x80 >> bytesNeeded) - 1;	// Available data bits in the leading byte.
-	if ( temp > mask ) ++bytesNeeded;
-
-	if ( bytesNeeded > utf8Len ) goto Done;	// Not enough room for the output.
-	unitCount = bytesNeeded;
-	
-	temp = cpIn;
-	for ( --bytesNeeded; bytesNeeded > 0; --bytesNeeded ) {
-		utf8Out[bytesNeeded] = 0x80 | UTF8Unit ( temp & 0x3F );
-		temp = temp >> 6;
-	}
-	
-	mask = ~((1 << (8-unitCount)) - 1);
-	utf8Out[0] = UTF8Unit ( mask | temp );
-
-Done:
-	*utf8Written = unitCount;
-	return;
-	
-}	// CodePoint_to_UTF8_Multi
-
-// =================================================================================================
-
-void CodePoint_to_UTF8 ( const UTF32Unit cpIn, UTF8Unit * utf8Out, const size_t utf8Len, size_t * utf8Written )
-{
-	size_t unitCount = 0;
-
-	UC_Assert ( (utf8Out != 0) && (utf8Written != 0) );
-	if ( utf8Len == 0 ) goto Done;
-	if ( cpIn > 0x7F ) goto MultiByte;	// ! Force linear execution path for ASCII.
-	
-	if ( utf8Len == 0 ) goto Done;
-	unitCount = 1;
-	*utf8Out = UTF8Unit(cpIn);
-
-Done:
-	*utf8Written = unitCount;
-	return;
-	
-MultiByte:
-	 CodePoint_to_UTF8_Multi( cpIn, utf8Out, utf8Len, utf8Written );
-	 return;
-	
-}	// CodePoint_to_UTF8
-
-// =================================================================================================
-
-static void CodePoint_from_UTF8_Multi ( const UTF8Unit * utf8In, const size_t utf8Len, UTF32Unit * cpOut, size_t * utf8Read )
-{
-	UTF8Unit  inUnit = *utf8In;
-	size_t    unitCount = 0;
-	UTF32Unit cp;	// ! Avoid gcc complaints about declarations after goto's.
-	const UTF8Unit * utf8Pos;
-
-	// -------------------------------------------------------------------------------------
-	// We've got a multibyte UTF-8 character. The first byte has the number of bytes and the
-	// highest order data bits. The other bytes each add 6 more data bits.
-	
-	#if 0	// This might be a more effcient way to count the bytes.
-		static XMP_Uns8 kByteCounts[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 2, 2, 3, 4 };
-		size_t bytesNeeded = kByteCounts [ inUnit >> 4 ];
-		if ( (bytesNeeded < 2) || ((bytesNeeded == 4) && ((inUnit & 0x08) != 0)) ) {
-			UC_Throw ( "Invalid UTF-8 sequence length", kXMPErr_BadParam );
-		}
-	#endif
-
-	size_t bytesNeeded = 0;	// Count the leading 1 bits in the first byte.
-	for ( UTF8Unit temp = inUnit; temp > 0x7F; temp = temp << 1 ) ++bytesNeeded;
-		// *** Consider CPU-specific assembly inline, e.g. cntlzw on PowerPC.
-	
-	if ( (bytesNeeded < 2) || (bytesNeeded > 4) ) UC_Throw ( "Invalid UTF-8 sequence length", kXMPErr_BadParam );
-	if ( bytesNeeded > utf8Len ) goto Done;	// Not enough input in this buffer.
-	unitCount = bytesNeeded;
-	
-	cp = inUnit & ((1 << (7-unitCount)) - 1);	// Isolate the initial data bits in the bottom of cp.
-	
-	utf8Pos = utf8In + 1;	// We've absorbed the first byte.
-	for ( --bytesNeeded; bytesNeeded > 0; --bytesNeeded, ++utf8Pos ) {
-		inUnit = *utf8Pos;
-		if ( (inUnit & UTF8Unit(0xC0)) != UTF8Unit(0x80) ) UC_Throw ( "Invalid UTF-8 data byte", kXMPErr_BadParam );
-		cp = (cp << 6) | (inUnit & 0x3F);
-	}
-	
-	if ( cp >= 0xD800 ) {	// Skip the next comparisons most of the time.
-		if ( (0xD800 <= cp) && (cp <= 0xDFFF) ) UC_Throw ( "Bad UTF-8 - surrogate code point", kXMPErr_BadParam );
-		if ( cp > 0x10FFFF ) UC_Throw ( "Bad UTF-8 - out of range", kXMPErr_BadParam );
-	}
-	
-	*cpOut = cp;	// ! Don't put after Done, don't write if no input.
-	
-Done:	
-	*utf8Read = unitCount;
-	return;
-	
-}	// CodePoint_from_UTF8_Multi
-
-// =================================================================================================
-
-void CodePoint_from_UTF8 ( const UTF8Unit * utf8In, const size_t utf8Len, UTF32Unit * cpOut, size_t * utf8Read )
-{
-	UTF8Unit inUnit;	// ! Don't read until we know there is input.
-	size_t unitCount = 0;
-
-	UC_Assert ( (utf8In != 0) && (cpOut != 0) && (utf8Read != 0) );
-	if ( utf8Len == 0 ) goto Done;
-	inUnit = *utf8In;
-	if ( inUnit >= 0x80 ) goto MultiByte;	// ! Force linear execution path for ASCII.
-	
-	unitCount = 1;
-	*cpOut = inUnit;	// ! Don't put after Done, don't write if no input.
-	
-Done:	
-	*utf8Read = unitCount;
-	return;
-
-MultiByte:
-	CodePoint_from_UTF8_Multi ( utf8In, utf8Len, cpOut, utf8Read );
-	return;
-	
-}	// CodePoint_from_UTF8
-
-// =================================================================================================
-
-static void CodePoint_to_UTF16Nat_Surrogate ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written )
-{
-	size_t    unitCount = 0;
-	UTF32Unit temp;	// ! Avoid gcc complaints about declarations after goto's.
-
-	if ( cpIn > 0x10FFFF ) UC_Throw ( "Bad UTF-32 - out of range", kXMPErr_BadParam );
-	if ( utf16Len < 2 ) goto Done;	// Not enough room for the output.
-
-	unitCount = 2;
-	temp = cpIn - 0x10000;
-	utf16Out[0] = 0xD800 | UTF16Unit ( temp >> 10 );
-	utf16Out[1] = 0xDC00 | UTF16Unit ( temp & 0x3FF );
-	
-Done:
-	*utf16Written = unitCount;
-	return;
-	
-}	// CodePoint_to_UTF16Nat_Surrogate
-
-// =================================================================================================
-
-static void CodePoint_to_UTF16Nat ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written )
-{
-	size_t unitCount = 0;
-
-	UC_Assert ( (utf16Out != 0) && (utf16Written != 0) );	
-	if ( utf16Len == 0 ) goto Done;
-	if ( cpIn >= 0xD800 ) goto CheckSurrogate;	// ! Force linear execution path for the BMP.
-
-InBMP:	
-	unitCount = 1;
-	*utf16Out = UTF16Unit(cpIn);
-	
-Done:
-	*utf16Written = unitCount;
-	return;
-
-CheckSurrogate:
-	if ( cpIn > 0xFFFF ) goto SurrogatePair;
-	if ( cpIn > 0xDFFF ) goto InBMP;
-	UC_Throw ( "Bad UTF-32 - surrogate code point", kXMPErr_BadParam );
-	
-SurrogatePair:
-	CodePoint_to_UTF16Nat_Surrogate ( cpIn, utf16Out, utf16Len, utf16Written );
-	return;
-	
-}	// CodePoint_to_UTF16Nat
-
-// =================================================================================================
-
-static void CodePoint_from_UTF16Nat_Surrogate ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read )
-{
-	UTF16Unit hiUnit = *utf16In;
-	size_t    unitCount = 0;
-	UTF16Unit loUnit;	// ! Avoid gcc complaints about declarations after goto's.
-	UTF32Unit cp;
-
-	// ----------------------------------
-	// We've got a UTF-16 surrogate pair.
-
-	if ( hiUnit > 0xDBFF ) UC_Throw ( "Bad UTF-16 - leading low surrogate", kXMPErr_BadParam );
-	if ( utf16Len < 2 ) goto Done;	// Not enough input in this buffer.
-	
-	loUnit  = *(utf16In+1);
-	if ( (loUnit < 0xDC00) || (0xDFFF < loUnit) ) UC_Throw ( "Bad UTF-16 - missing low surrogate", kXMPErr_BadParam );
-	
-	unitCount = 2;
-	cp = (((hiUnit & 0x3FF) << 10) | (loUnit & 0x3FF)) + 0x10000;
-
-	*cpOut = cp;	// ! Don't put after Done, don't write if no input.
-	
-Done:
-	*utf16Read = unitCount;
-	return;
-	
-}	// CodePoint_from_UTF16Nat_Surrogate
-
-// =================================================================================================
-
-static void CodePoint_from_UTF16Nat ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read )
-{
-	UTF16Unit inUnit;	// ! Don't read until we know there is input.
-	size_t unitCount = 0;
-
-	UC_Assert ( (utf16In != 0) && (cpOut != 0) && (utf16Read != 0) );
-	if ( utf16Len == 0 ) goto Done;
-	inUnit = *utf16In;
-	if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) goto SurrogatePair;	// ! Force linear execution path for the BMP.
-
-	unitCount = 1;
-	*cpOut = inUnit;	// ! Don't put after Done, don't write if no input.
-	
-Done:
-	*utf16Read = unitCount;
-	return;
-
-SurrogatePair:
-	CodePoint_from_UTF16Nat_Surrogate ( utf16In, utf16Len, cpOut, utf16Read );
-	return;
-	
-}	// CodePoint_from_UTF16Nat
-
-// =================================================================================================
-
-static void UTF8_to_UTF16Nat ( const UTF8Unit * utf8In,   const size_t utf8Len,
-				               UTF16Unit *      utf16Out, const size_t utf16Len,
-				               size_t *         utf8Read, size_t *     utf16Written )
-{
-	const UTF8Unit * utf8Pos  = utf8In;
-	UTF16Unit *      utf16Pos = utf16Out;
-	
-	size_t utf8Left  = utf8Len;
-	size_t utf16Left = utf16Len;
-	
-	UC_Assert ( (utf8In != 0) && (utf16Out != 0) && (utf8Read != 0) && (utf16Written != 0) );
-	
-	while ( (utf8Left > 0) && (utf16Left > 0) ) {
-	
-		// Do a run of ASCII, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf8Left;
-		if ( limit > utf16Left ) limit = utf16Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF8Unit inUnit = *utf8Pos;
-			if ( inUnit > 0x7F ) break;
-			*utf16Pos = inUnit;
-			++utf8Pos;
-			++utf16Pos;
-		}
-		utf8Left  -= i;
-		utf16Left -= i;
-		
-		// Do a run of non-ASCII, it copies multiple input units into 1 or 2 output units.
-		while ( (utf8Left > 0) && (utf16Left > 0) ) {
-			UTF32Unit cp;
-			size_t len8, len16;
-			UTF8Unit inUnit = *utf8Pos;
-			if ( inUnit <= 0x7F ) break;
-			CodePoint_from_UTF8_Multi ( utf8Pos, utf8Left, &cp, &len8 );
-			if ( len8 == 0 ) goto Done;		// The input buffer ends in the middle of a character.
-			if ( cp <= 0xFFFF ) {
-				*utf16Pos = UTF16Unit(cp);
-				len16 = 1;
-			} else {
-				CodePoint_to_UTF16Nat_Surrogate ( cp, utf16Pos, utf16Left, &len16 );
-				if ( len16 == 0 ) goto Done;	// Not enough room in the output buffer.
-			}
-			utf8Left  -= len8;
-			utf8Pos   += len8;
-			utf16Left -= len16;
-			utf16Pos  += len16;
-		}
-	
-	}
-
-Done:	// Set the output lengths.
-	*utf8Read = utf8Len - utf8Left;
-	*utf16Written = utf16Len - utf16Left;
-	
-}	// UTF8_to_UTF16Nat
-
-// =================================================================================================
-
-static void UTF8_to_UTF32Nat ( const UTF8Unit *  utf8In,   const size_t utf8Len,
-				               UTF32Unit *       utf32Out, const size_t utf32Len,
-				               size_t *          utf8Read, size_t *     utf32Written )
-{
-	const UTF8Unit * utf8Pos  = utf8In;
-	UTF32Unit *      utf32Pos = utf32Out;
-	
-	size_t utf8Left  = utf8Len;
-	size_t utf32Left = utf32Len;
-	
-	UC_Assert ( (utf8In != 0) && (utf32Out != 0) && (utf8Read != 0) && (utf32Written != 0) );
-	
-	while ( (utf8Left > 0) && (utf32Left > 0) ) {
-	
-		// Do a run of ASCII, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf8Left;
-		if ( limit > utf32Left ) limit = utf32Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF8Unit inUnit = *utf8Pos;
-			if ( inUnit > 0x7F ) break;
-			*utf32Pos = inUnit;
-			++utf8Pos;
-			++utf32Pos;
-		}
-		utf8Left -= i;
-		utf32Left -= i;
-		
-		// Do a run of non-ASCII, it copies variable input into 1 output unit.
-		while ( (utf8Left > 0) && (utf32Left > 0) ) {
-			size_t len;
-			UTF8Unit inUnit = *utf8Pos;
-			if ( inUnit <= 0x7F ) break;
-			CodePoint_from_UTF8_Multi ( utf8Pos, utf8Left, utf32Pos, &len );
-			if ( len == 0 ) goto Done;	// The input buffer ends in the middle of a character.
-			utf8Left  -= len;
-			utf8Pos   += len;
-			utf32Left -= 1;
-			utf32Pos  += 1;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf8Read = utf8Len - utf8Left;
-	*utf32Written = utf32Len - utf32Left;
-	
-}	// UTF8_to_UTF32Nat
-
-// =================================================================================================
-
-static void UTF16Nat_to_UTF8 ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				               UTF8Unit *        utf8Out,   const size_t utf8Len,
-				               size_t *          utf16Read, size_t *     utf8Written )
-{
-	const UTF16Unit * utf16Pos = utf16In;
-	UTF8Unit *        utf8Pos  = utf8Out;
-	
-	size_t utf16Left = utf16Len;
-	size_t utf8Left  = utf8Len;
-	
-	UC_Assert ( (utf16In != 0) && (utf8Out != 0) && (utf16Read != 0) && (utf8Written != 0) );
-	
-	while ( (utf16Left > 0) && (utf8Left > 0) ) {
-	
-		// Do a run of ASCII, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf16Left;
-		if ( limit > utf8Left ) limit = utf8Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF16Unit inUnit = *utf16Pos;
-			if ( inUnit > 0x7F ) break;
-			*utf8Pos = UTF8Unit(inUnit);
-			++utf16Pos;
-			++utf8Pos;
-		}
-		utf16Left -= i;
-		utf8Left  -= i;
-		
-		// Do a run of non-ASCII inside the BMP, it copies 1 input unit into multiple output units.
-		while ( (utf16Left > 0) && (utf8Left > 0) ) {
-			size_t len8;
-			UTF16Unit inUnit = *utf16Pos;
-			if ( inUnit <= 0x7F ) break;
-			if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break;
-			CodePoint_to_UTF8_Multi ( inUnit, utf8Pos, utf8Left, &len8 );
-			if ( len8 == 0 ) goto Done;		// Not enough room in the output buffer.
-			utf16Left -= 1;
-			utf16Pos  += 1;
-			utf8Left  -= len8;
-			utf8Pos   += len8;
-		}
-		
-		// Do a run of surrogate pairs, it copies 2 input units into multiple output units.
-		while ( (utf16Left > 0) && (utf8Left > 0) ) {
-			UTF32Unit cp;
-			size_t len16, len8;
-			UTF16Unit inUnit = *utf16Pos;
-			if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break;
-			CodePoint_from_UTF16Nat_Surrogate ( utf16Pos, utf16Left, &cp, &len16 );
-			if ( len16 == 0 ) goto Done;	// The input buffer ends in the middle of a surrogate pair.
-			UC_Assert ( len16 == 2 );
-			CodePoint_to_UTF8_Multi ( cp, utf8Pos, utf8Left, &len8 );
-			if ( len8 == 0 ) goto Done;		// Not enough room in the output buffer.
-			utf16Left -= len16;
-			utf16Pos  += len16;
-			utf8Left  -= len8;
-			utf8Pos   += len8;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf16Read = utf16Len - utf16Left;
-	*utf8Written = utf8Len - utf8Left;
-	
-}	// UTF16Nat_to_UTF8
-
-// =================================================================================================
-
-static void UTF32Nat_to_UTF8 ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				               UTF8Unit *        utf8Out,   const size_t utf8Len,
-				               size_t *          utf32Read, size_t *     utf8Written )
-{
-	const UTF32Unit * utf32Pos = utf32In;
-	UTF8Unit *        utf8Pos  = utf8Out;
-	
-	size_t utf32Left = utf32Len;
-	size_t utf8Left  = utf8Len;
-	
-	UC_Assert ( (utf32In != 0) && (utf8Out != 0) && (utf32Read != 0) && (utf8Written != 0) );
-	
-	while ( (utf32Left > 0) && (utf8Left > 0) ) {
-	
-		// Do a run of ASCII, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf32Left;
-		if ( limit > utf8Left ) limit = utf8Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF32Unit inUnit = *utf32Pos;
-			if ( inUnit > 0x7F ) break;
-			*utf8Pos = UTF8Unit(inUnit);
-			++utf32Pos;
-			++utf8Pos;
-		}
-		utf32Left -= i;
-		utf8Left  -= i;
-		
-		// Do a run of non-ASCII, it copies 1 input unit into multiple output units.
-		while ( (utf32Left > 0) && (utf8Left > 0) ) {
-			size_t len;
-			UTF32Unit inUnit = *utf32Pos;
-			if ( inUnit <= 0x7F ) break;
-			CodePoint_to_UTF8_Multi ( inUnit, utf8Pos, utf8Left, &len );
-			if ( len == 0 ) goto Done;	// Not enough room in the output buffer.
-			utf32Left -= 1;
-			utf32Pos  += 1;
-			utf8Left  -= len;
-			utf8Pos   += len;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf32Read = utf32Len - utf32Left;
-	*utf8Written = utf8Len - utf8Left;
-	
-}	// UTF32Nat_to_UTF8
-
-// =================================================================================================
-
-static void UTF16Nat_to_UTF32Nat ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				                   UTF32Unit *       utf32Out,  const size_t utf32Len,
-				                   size_t *          utf16Read, size_t *     utf32Written )
-{
-	const UTF16Unit * utf16Pos = utf16In;
-	UTF32Unit *       utf32Pos = utf32Out;
-	
-	size_t utf16Left = utf16Len;
-	size_t utf32Left = utf32Len;
-	
-	UC_Assert ( (utf16In != 0) && (utf32Out != 0) && (utf16Read != 0) && (utf32Written != 0) );
-	
-	while ( (utf16Left > 0) && (utf32Left > 0) ) {
-	
-		// Do a run of BMP, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf16Left;
-		if ( limit > utf32Left ) limit = utf32Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF16Unit inUnit = *utf16Pos;
-			if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break;
-			*utf32Pos = inUnit;
-			++utf16Pos;
-			++utf32Pos;
-		}
-		utf16Left -= i;
-		utf32Left -= i;
-		
-		// Do a run of surrogate pairs, it copies 2 input units into 1 output unit.
-		while ( (utf16Left > 0) && (utf32Left > 0) ) {
-			size_t len;
-			UTF16Unit inUnit = *utf16Pos;
-			if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break;
-			CodePoint_from_UTF16Nat_Surrogate ( utf16Pos, utf16Left, utf32Pos, &len );
-			if ( len == 0 ) goto Done;	// The input buffer ends in the middle of a surrogate pair.
-			UC_Assert ( len == 2 );
-			utf16Left -= len;
-			utf16Pos  += len;
-			utf32Left -= 1;
-			utf32Pos  += 1;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf16Read = utf16Len - utf16Left;
-	*utf32Written = utf32Len - utf32Left;
-	
-}	// UTF16Nat_to_UTF32Nat
-
-// =================================================================================================
-
-static void UTF32Nat_to_UTF16Nat ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				                   UTF16Unit *       utf16Out,  const size_t utf16Len,
-				                   size_t *          utf32Read, size_t *     utf16Written )
-{
-	const UTF32Unit * utf32Pos = utf32In;
-	UTF16Unit *       utf16Pos = utf16Out;
-	
-	size_t utf32Left = utf32Len;
-	size_t utf16Left = utf16Len;
-	
-	UC_Assert ( (utf32In != 0) && (utf16Out != 0) && (utf32Read != 0) && (utf16Written != 0) );
-	
-	while ( (utf32Left > 0) && (utf16Left > 0) ) {
-	
-		// Do a run of BMP, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf32Left;
-		if ( limit > utf16Left ) limit = utf16Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF32Unit inUnit = *utf32Pos;
-			if ( inUnit > 0xFFFF ) break;
-			*utf16Pos = UTF16Unit(inUnit);
-			++utf32Pos;
-			++utf16Pos;
-		}
-		utf32Left -= i;
-		utf16Left -= i;
-		
-		// Do a run of non-BMP, it copies 1 input unit into 2 output units.
-		while ( (utf32Left > 0) && (utf16Left > 0) ) {
-			size_t len;
-			UTF32Unit inUnit = *utf32Pos;
-			if ( inUnit <= 0xFFFF ) break;
-			CodePoint_to_UTF16Nat_Surrogate ( inUnit, utf16Pos, utf16Left, &len );
-			if ( len == 0 ) goto Done;	// Not enough room in the output buffer.
-			UC_Assert ( len == 2 );
-			utf32Left -= 1;
-			utf32Pos  += 1;
-			utf16Left -= 2;
-			utf16Pos  += 2;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf32Read = utf32Len - utf32Left;
-	*utf16Written = utf16Len - utf16Left;
-	
-}	// UTF32Nat_to_UTF16Nat
-
-// =================================================================================================
-
-static void CodePoint_to_UTF16Swp_Surrogate ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written )
-{
-	size_t unitCount = 0;
-	UTF32Unit temp;	// ! Avoid gcc complaints about declarations after goto's.
-
-	if ( cpIn > 0x10FFFF ) UC_Throw ( "Bad UTF-32 - out of range", kXMPErr_BadParam );
-	if ( utf16Len < 2 ) goto Done;	// Not enough room for the output.
-
-	unitCount = 2;
-	temp = cpIn - 0x10000;
-	UTF16OutSwap ( &utf16Out[0], (0xD800 | UTF16Unit ( temp >> 10 )) );
-	UTF16OutSwap ( &utf16Out[1], (0xDC00 | UTF16Unit ( temp & 0x3FF)) );
-	
-Done:
-	*utf16Written = unitCount;
-	return;
-	
-}	// CodePoint_to_UTF16Swp_Surrogate
-
-// =================================================================================================
-
-static void CodePoint_to_UTF16Swp ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written )
-{
-	size_t unitCount = 0;
-
-	UC_Assert ( (utf16Out != 0) && (utf16Written != 0) );	
-	if ( utf16Len == 0 ) goto Done;
-	if ( cpIn >= 0xD800 ) goto CheckSurrogate;	// ! Force linear execution path for the BMP.
-
-InBMP:	
-	unitCount = 1;
-	UTF16OutSwap ( utf16Out, UTF16Unit(cpIn) );
-	
-Done:
-	*utf16Written = unitCount;
-	return;
-
-CheckSurrogate:
-	if ( cpIn > 0xFFFF ) goto SurrogatePair;
-	if ( cpIn > 0xDFFF ) goto InBMP;
-	UC_Throw ( "Bad UTF-32 - surrogate code point", kXMPErr_BadParam );
-	
-SurrogatePair:
-	CodePoint_to_UTF16Swp_Surrogate ( cpIn, utf16Out, utf16Len, utf16Written );
-	return;
-	
-}	// CodePoint_to_UTF16Swp
-
-// =================================================================================================
-
-static void CodePoint_from_UTF16Swp_Surrogate ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read )
-{
-	UTF16Unit hiUnit = UTF16InSwap(utf16In);
-	size_t unitCount = 0;
-	UTF16Unit loUnit;	// ! Avoid gcc complaints about declarations after goto's.
-	UTF32Unit cp;
-
-	// ----------------------------------
-	// We've got a UTF-16 surrogate pair.
-
-	if ( hiUnit > 0xDBFF ) UC_Throw ( "Bad UTF-16 - leading low surrogate", kXMPErr_BadParam );
-	if ( utf16Len < 2 ) goto Done;	// Not enough input in this buffer.
-	
-	loUnit  = UTF16InSwap(utf16In+1);
-	if ( (loUnit < 0xDC00) || (0xDFFF < loUnit) ) UC_Throw ( "Bad UTF-16 - missing low surrogate", kXMPErr_BadParam );
-	
-	unitCount = 2;
-	cp = (((hiUnit & 0x3FF) << 10) | (loUnit & 0x3FF)) + 0x10000;
-
-	*cpOut = cp;	// ! Don't put after Done, don't write if no input.
-	
-Done:
-	*utf16Read = unitCount;
-	return;
-	
-}	// CodePoint_from_UTF16Swp_Surrogate
-
-// =================================================================================================
-
-static void CodePoint_from_UTF16Swp ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read )
-{
-	UTF16Unit inUnit;	// ! Don't read until we know there is input.
-	size_t unitCount = 0;
-
-	UC_Assert ( (utf16In != 0) && (cpOut != 0) && (utf16Read != 0) );
-	if ( utf16Len == 0 ) goto Done;
-	inUnit = UTF16InSwap(utf16In);
-	if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) goto SurrogatePair;	// ! Force linear execution path for the BMP.
-
-	unitCount = 1;
-	*cpOut = inUnit;	// ! Don't put after Done, don't write if no input.
-	
-Done:
-	*utf16Read = unitCount;
-	return;
-
-SurrogatePair:
-	CodePoint_from_UTF16Swp_Surrogate ( utf16In, utf16Len, cpOut, utf16Read );
-	return;
-	
-}	// CodePoint_from_UTF16Swp
-
-// =================================================================================================
-
-static void UTF8_to_UTF16Swp ( const UTF8Unit * utf8In,   const size_t utf8Len,
-				               UTF16Unit *      utf16Out, const size_t utf16Len,
-				               size_t *         utf8Read, size_t *     utf16Written )
-{
-	const UTF8Unit * utf8Pos  = utf8In;
-	UTF16Unit *      utf16Pos = utf16Out;
-	
-	size_t utf8Left  = utf8Len;
-	size_t utf16Left = utf16Len;
-	
-	UC_Assert ( (utf8In != 0) && (utf16Out != 0) && (utf8Read != 0) && (utf16Written != 0) );
-	
-	while ( (utf8Left > 0) && (utf16Left > 0) ) {
-	
-		// Do a run of ASCII, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf8Left;
-		if ( limit > utf16Left ) limit = utf16Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF8Unit inUnit = *utf8Pos;
-			if ( inUnit > 0x7F ) break;
-			*utf16Pos = UTF16Unit(inUnit) << 8;	// Better than: UTF16OutSwap ( utf16Pos, inUnit );
-			++utf8Pos;
-			++utf16Pos;
-		}
-		utf8Left  -= i;
-		utf16Left -= i;
-		
-		// Do a run of non-ASCII, it copies multiple input units into 1 or 2 output units.
-		while ( (utf8Left > 0) && (utf16Left > 0) ) {
-			UTF32Unit cp;
-			size_t len8, len16;
-			UTF8Unit inUnit = *utf8Pos;
-			if ( inUnit <= 0x7F ) break;
-			CodePoint_from_UTF8_Multi ( utf8Pos, utf8Left, &cp, &len8 );
-			if ( len8 == 0 ) goto Done;		// The input buffer ends in the middle of a character.
-			if ( cp <= 0xFFFF ) {
-				UTF16OutSwap ( utf16Pos, UTF16Unit(cp) );
-				len16 = 1;
-			} else {
-				CodePoint_to_UTF16Swp_Surrogate ( cp, utf16Pos, utf16Left, &len16 );
-				if ( len16 == 0 ) goto Done;	// Not enough room in the output buffer.
-			}
-			utf8Left  -= len8;
-			utf8Pos   += len8;
-			utf16Left -= len16;
-			utf16Pos  += len16;
-		}
-	
-	}
-
-Done:	// Set the output lengths.
-	*utf8Read = utf8Len - utf8Left;
-	*utf16Written = utf16Len - utf16Left;
-	
-}	// UTF8_to_UTF16Swp
-
-// =================================================================================================
-
-static void UTF8_to_UTF32Swp ( const UTF8Unit *  utf8In,   const size_t utf8Len,
-				               UTF32Unit *       utf32Out, const size_t utf32Len,
-				               size_t *          utf8Read, size_t *     utf32Written )
-{
-	const UTF8Unit * utf8Pos  = utf8In;
-	UTF32Unit *      utf32Pos = utf32Out;
-	
-	size_t utf8Left  = utf8Len;
-	size_t utf32Left = utf32Len;
-	
-	UC_Assert ( (utf8In != 0) && (utf32Out != 0) && (utf8Read != 0) && (utf32Written != 0) );
-	
-	while ( (utf8Left > 0) && (utf32Left > 0) ) {
-	
-		// Do a run of ASCII, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf8Left;
-		if ( limit > utf32Left ) limit = utf32Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF8Unit inUnit = *utf8Pos;
-			if ( inUnit > 0x7F ) break;
-			*utf32Pos = UTF32Unit(inUnit) << 24;	// Better than: UTF32OutSwap ( utf32Pos, inUnit );
-			++utf8Pos;
-			++utf32Pos;
-		}
-		utf8Left -= i;
-		utf32Left -= i;
-		
-		// Do a run of non-ASCII, it copies variable input into 1 output unit.
-		while ( (utf8Left > 0) && (utf32Left > 0) ) {
-			size_t len;
-			UTF32Unit cp;
-			UTF8Unit inUnit = *utf8Pos;
-			if ( inUnit <= 0x7F ) break;
-			CodePoint_from_UTF8_Multi ( utf8Pos, utf8Left, &cp, &len );
-			if ( len == 0 ) goto Done;	// The input buffer ends in the middle of a character.
-			UTF32OutSwap ( utf32Pos, cp );
-			utf8Left  -= len;
-			utf8Pos   += len;
-			utf32Left -= 1;
-			utf32Pos  += 1;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf8Read = utf8Len - utf8Left;
-	*utf32Written = utf32Len - utf32Left;
-	
-}	// UTF8_to_UTF32Swp
-
-// =================================================================================================
-
-static void UTF16Swp_to_UTF8 ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				               UTF8Unit *        utf8Out,   const size_t utf8Len,
-				               size_t *          utf16Read, size_t *     utf8Written )
-{
-	const UTF16Unit * utf16Pos = utf16In;
-	UTF8Unit *        utf8Pos  = utf8Out;
-	
-	size_t utf16Left = utf16Len;
-	size_t utf8Left  = utf8Len;
-	
-	UC_Assert ( (utf16In != 0) && (utf8Out != 0) && (utf16Read != 0) && (utf8Written != 0) );
-	
-	while ( (utf16Left > 0) && (utf8Left > 0) ) {
-	
-		// Do a run of ASCII, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf16Left;
-		if ( limit > utf8Left ) limit = utf8Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF16Unit inUnit = UTF16InSwap(utf16Pos);
-			if ( inUnit > 0x7F ) break;
-			*utf8Pos = UTF8Unit(inUnit);
-			++utf16Pos;
-			++utf8Pos;
-		}
-		utf16Left -= i;
-		utf8Left  -= i;
-		
-		// Do a run of non-ASCII inside the BMP, it copies 1 input unit into multiple output units.
-		while ( (utf16Left > 0) && (utf8Left > 0) ) {
-			size_t len8;
-			UTF16Unit inUnit = UTF16InSwap(utf16Pos);
-			if ( inUnit <= 0x7F ) break;
-			if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break;
-			CodePoint_to_UTF8_Multi ( inUnit, utf8Pos, utf8Left, &len8 );
-			if ( len8 == 0 ) goto Done;		// Not enough room in the output buffer.
-			utf16Left -= 1;
-			utf16Pos  += 1;
-			utf8Left  -= len8;
-			utf8Pos   += len8;
-		}
-		
-		// Do a run of surrogate pairs, it copies 2 input units into multiple output units.
-		while ( (utf16Left > 0) && (utf8Left > 0) ) {
-			UTF32Unit cp;
-			size_t len16, len8;
-			UTF16Unit inUnit = UTF16InSwap(utf16Pos);
-			if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break;
-			CodePoint_from_UTF16Swp_Surrogate ( utf16Pos, utf16Left, &cp, &len16 );
-			if ( len16 == 0 ) goto Done;	// The input buffer ends in the middle of a surrogate pair.
-			UC_Assert ( len16 == 2 );
-			CodePoint_to_UTF8_Multi ( cp, utf8Pos, utf8Left, &len8 );
-			if ( len8 == 0 ) goto Done;		// Not enough room in the output buffer.
-			utf16Left -= len16;
-			utf16Pos  += len16;
-			utf8Left  -= len8;
-			utf8Pos   += len8;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf16Read = utf16Len - utf16Left;
-	*utf8Written = utf8Len - utf8Left;
-	
-}	// UTF16Swp_to_UTF8
-
-// =================================================================================================
-
-static void UTF32Swp_to_UTF8 ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				               UTF8Unit *        utf8Out,   const size_t utf8Len,
-				               size_t *          utf32Read, size_t *     utf8Written )
-{
-	const UTF32Unit * utf32Pos = utf32In;
-	UTF8Unit *        utf8Pos  = utf8Out;
-	
-	size_t utf32Left = utf32Len;
-	size_t utf8Left  = utf8Len;
-	
-	UC_Assert ( (utf32In != 0) && (utf8Out != 0) && (utf32Read != 0) && (utf8Written != 0) );
-	
-	while ( (utf32Left > 0) && (utf8Left > 0) ) {
-	
-		// Do a run of ASCII, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf32Left;
-		if ( limit > utf8Left ) limit = utf8Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF32Unit cp = UTF32InSwap(utf32Pos);
-			if ( cp > 0x7F ) break;
-			*utf8Pos = UTF8Unit(cp);
-			++utf32Pos;
-			++utf8Pos;
-		}
-		utf32Left -= i;
-		utf8Left  -= i;
-		
-		// Do a run of non-ASCII, it copies 1 input unit into multiple output units.
-		while ( (utf32Left > 0) && (utf8Left > 0) ) {
-			size_t len;
-			UTF32Unit cp = UTF32InSwap(utf32Pos);
-			if ( cp <= 0x7F ) break;
-			CodePoint_to_UTF8_Multi ( cp, utf8Pos, utf8Left, &len );
-			if ( len == 0 ) goto Done;	// Not enough room in the output buffer.
-			utf32Left -= 1;
-			utf32Pos  += 1;
-			utf8Left  -= len;
-			utf8Pos   += len;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf32Read = utf32Len - utf32Left;
-	*utf8Written = utf8Len - utf8Left;
-	
-}	// UTF32Swp_to_UTF8
-
-// =================================================================================================
-
-static void UTF16Swp_to_UTF32Swp ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				                   UTF32Unit *       utf32Out,  const size_t utf32Len,
-				                   size_t *          utf16Read, size_t *     utf32Written )
-{
-	const UTF16Unit * utf16Pos = utf16In;
-	UTF32Unit *       utf32Pos = utf32Out;
-	
-	size_t utf16Left = utf16Len;
-	size_t utf32Left = utf32Len;
-	
-	UC_Assert ( (utf16In != 0) && (utf32Out != 0) && (utf16Read != 0) && (utf32Written != 0) );
-	
-	while ( (utf16Left > 0) && (utf32Left > 0) ) {
-	
-		// Do a run of BMP, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf16Left;
-		if ( limit > utf32Left ) limit = utf32Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF16Unit inUnit = UTF16InSwap(utf16Pos);
-			if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break;
-			*utf32Pos = UTF32Unit(*utf16Pos) << 16;	// Better than: UTF32OutSwap ( utf32Pos, inUnit );
-			++utf16Pos;
-			++utf32Pos;
-		}
-		utf16Left -= i;
-		utf32Left -= i;
-		
-		// Do a run of surrogate pairs, it copies 2 input units into 1 output unit.
-		while ( (utf16Left > 0) && (utf32Left > 0) ) {
-			size_t len;
-			UTF32Unit cp;
-			UTF16Unit inUnit = UTF16InSwap(utf16Pos);
-			if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break;
-			CodePoint_from_UTF16Swp_Surrogate ( utf16Pos, utf16Left, &cp, &len );
-			if ( len == 0 ) goto Done;	// The input buffer ends in the middle of a surrogate pair.
-			UTF32OutSwap ( utf32Pos, cp );
-			UC_Assert ( len == 2 );
-			utf16Left -= len;
-			utf16Pos  += len;
-			utf32Left -= 1;
-			utf32Pos  += 1;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf16Read = utf16Len - utf16Left;
-	*utf32Written = utf32Len - utf32Left;
-	
-}	// UTF16Swp_to_UTF32Swp
-
-// =================================================================================================
-
-static void UTF32Swp_to_UTF16Swp ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				                   UTF16Unit *       utf16Out,  const size_t utf16Len,
-				                   size_t *          utf32Read, size_t *     utf16Written )
-{
-	const UTF32Unit * utf32Pos = utf32In;
-	UTF16Unit *       utf16Pos = utf16Out;
-	
-	size_t utf32Left = utf32Len;
-	size_t utf16Left = utf16Len;
-	
-	const size_t k32to16Offset = swap32to16Offset;	// ! Make sure compiler treats as an invariant.
-	
-	UC_Assert ( (utf32In != 0) && (utf16Out != 0) && (utf32Read != 0) && (utf16Written != 0) );
-	
-	while ( (utf32Left > 0) && (utf16Left > 0) ) {
-	
-		// Do a run of BMP, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf32Left;
-		if ( limit > utf16Left ) limit = utf16Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF32Unit inUnit = UTF32InSwap(utf32Pos);
-			if ( inUnit > 0xFFFF ) break;
-			*utf16Pos = *(((UTF16Unit*)utf32Pos) + k32to16Offset);	// Better than: UTF16OutSwap ( utf16Pos, UTF16Unit(inUnit) );
-			++utf32Pos;
-			++utf16Pos;
-		}
-		utf32Left -= i;
-		utf16Left -= i;
-		
-		// Do a run of non-BMP, it copies 1 input unit into 2 output units.
-		while ( (utf32Left > 0) && (utf16Left > 0) ) {
-			size_t len;
-			UTF32Unit inUnit = UTF32InSwap(utf32Pos);
-			if ( inUnit <= 0xFFFF ) break;
-			CodePoint_to_UTF16Swp_Surrogate ( inUnit, utf16Pos, utf16Left, &len );
-			if ( len == 0 ) goto Done;	// Not enough room in the output buffer.
-			UC_Assert ( len == 2 );
-			utf32Left -= 1;
-			utf32Pos  += 1;
-			utf16Left -= 2;
-			utf16Pos  += 2;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf32Read = utf32Len - utf32Left;
-	*utf16Written = utf16Len - utf16Left;
-	
-}	// UTF32Swp_to_UTF16Swp
-
-// =================================================================================================
-
-static void UTF16Nat_to_UTF32Swp ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				                   UTF32Unit *       utf32Out,  const size_t utf32Len,
-				                   size_t *          utf16Read, size_t *     utf32Written )
-{
-	const UTF16Unit * utf16Pos = utf16In;
-	UTF32Unit *       utf32Pos = utf32Out;
-	
-	size_t utf16Left = utf16Len;
-	size_t utf32Left = utf32Len;
-	
-	UC_Assert ( (utf16In != 0) && (utf32Out != 0) && (utf16Read != 0) && (utf32Written != 0) );
-	
-	while ( (utf16Left > 0) && (utf32Left > 0) ) {
-	
-		// Do a run of BMP, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf16Left;
-		if ( limit > utf32Left ) limit = utf32Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF16Unit inUnit = *utf16Pos;
-			if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break;
-			UTF32OutSwap ( utf32Pos, inUnit );
-			++utf16Pos;
-			++utf32Pos;
-		}
-		utf16Left -= i;
-		utf32Left -= i;
-		
-		// Do a run of surrogate pairs, it copies 2 input units into 1 output unit.
-		while ( (utf16Left > 0) && (utf32Left > 0) ) {
-			size_t len;
-			UTF32Unit cp;
-			UTF16Unit inUnit = *utf16Pos;
-			if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break;
-			CodePoint_from_UTF16Nat_Surrogate ( utf16Pos, utf16Left, &cp, &len );
-			if ( len == 0 ) goto Done;	// The input buffer ends in the middle of a surrogate pair.
-			UC_Assert ( len == 2 );
-			UTF32OutSwap ( utf32Pos, cp );
-			utf16Left -= len;
-			utf16Pos  += len;
-			utf32Left -= 1;
-			utf32Pos  += 1;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf16Read = utf16Len - utf16Left;
-	*utf32Written = utf32Len - utf32Left;
-	
-}	// UTF16Nat_to_UTF32Swp
-
-// =================================================================================================
-
-static void UTF16Swp_to_UTF32Nat ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				                   UTF32Unit *       utf32Out,  const size_t utf32Len,
-				                   size_t *          utf16Read, size_t *     utf32Written )
-{
-	const UTF16Unit * utf16Pos = utf16In;
-	UTF32Unit *       utf32Pos = utf32Out;
-	
-	size_t utf16Left = utf16Len;
-	size_t utf32Left = utf32Len;
-	
-	UC_Assert ( (utf16In != 0) && (utf32Out != 0) && (utf16Read != 0) && (utf32Written != 0) );
-	
-	while ( (utf16Left > 0) && (utf32Left > 0) ) {
-	
-		// Do a run of BMP, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf16Left;
-		if ( limit > utf32Left ) limit = utf32Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF16Unit inUnit = UTF16InSwap(utf16Pos);
-			if ( (0xD800 <= inUnit) && (inUnit <= 0xDFFF) ) break;
-			*utf32Pos = inUnit;
-			++utf16Pos;
-			++utf32Pos;
-		}
-		utf16Left -= i;
-		utf32Left -= i;
-		
-		// Do a run of surrogate pairs, it copies 2 input units into 1 output unit.
-		while ( (utf16Left > 0) && (utf32Left > 0) ) {
-			size_t len;
-			UTF16Unit inUnit = UTF16InSwap(utf16Pos);
-			if ( (inUnit < 0xD800) || (0xDFFF < inUnit) ) break;
-			CodePoint_from_UTF16Swp_Surrogate ( utf16Pos, utf16Left, utf32Pos, &len );
-			if ( len == 0 ) goto Done;	// The input buffer ends in the middle of a surrogate pair.
-			UC_Assert ( len == 2 );
-			utf16Left -= len;
-			utf16Pos  += len;
-			utf32Left -= 1;
-			utf32Pos  += 1;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf16Read = utf16Len - utf16Left;
-	*utf32Written = utf32Len - utf32Left;
-	
-}	// UTF16Swp_to_UTF32Nat
-
-// =================================================================================================
-
-static void UTF32Nat_to_UTF16Swp ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				                   UTF16Unit *       utf16Out,  const size_t utf16Len,
-				                   size_t *          utf32Read, size_t *     utf16Written )
-{
-	const UTF32Unit * utf32Pos = utf32In;
-	UTF16Unit *       utf16Pos = utf16Out;
-	
-	size_t utf32Left = utf32Len;
-	size_t utf16Left = utf16Len;
-	
-	UC_Assert ( (utf32In != 0) && (utf16Out != 0) && (utf32Read != 0) && (utf16Written != 0) );
-	
-	while ( (utf32Left > 0) && (utf16Left > 0) ) {
-	
-		// Do a run of BMP, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf32Left;
-		if ( limit > utf16Left ) limit = utf16Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF32Unit inUnit = *utf32Pos;
-			if ( inUnit > 0xFFFF ) break;
-			UTF16OutSwap ( utf16Pos, UTF16Unit(inUnit) );
-			++utf32Pos;
-			++utf16Pos;
-		}
-		utf32Left -= i;
-		utf16Left -= i;
-		
-		// Do a run of non-BMP, it copies 1 input unit into 2 output units.
-		while ( (utf32Left > 0) && (utf16Left > 0) ) {
-			size_t len;
-			UTF32Unit inUnit = *utf32Pos;
-			if ( inUnit <= 0xFFFF ) break;
-			CodePoint_to_UTF16Swp_Surrogate ( inUnit, utf16Pos, utf16Left, &len );
-			if ( len == 0 ) goto Done;	// Not enough room in the output buffer.
-			UC_Assert ( len == 2 );
-			utf32Left -= 1;
-			utf32Pos  += 1;
-			utf16Left -= 2;
-			utf16Pos  += 2;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf32Read = utf32Len - utf32Left;
-	*utf16Written = utf16Len - utf16Left;
-	
-}	// UTF32Nat_to_UTF16Swp
-
-// =================================================================================================
-
-static void UTF32Swp_to_UTF16Nat ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				                   UTF16Unit *       utf16Out,  const size_t utf16Len,
-				                   size_t *          utf32Read, size_t *     utf16Written )
-{
-	const UTF32Unit * utf32Pos = utf32In;
-	UTF16Unit *       utf16Pos = utf16Out;
-	
-	size_t utf32Left = utf32Len;
-	size_t utf16Left = utf16Len;
-	
-	UC_Assert ( (utf32In != 0) && (utf16Out != 0) && (utf32Read != 0) && (utf16Written != 0) );
-	
-	while ( (utf32Left > 0) && (utf16Left > 0) ) {
-	
-		// Do a run of BMP, it copies 1 input unit into 1 output unit.
-		size_t i, limit = utf32Left;
-		if ( limit > utf16Left ) limit = utf16Left;
-		for ( i = 0; i < limit; ++i ) {
-			UTF32Unit inUnit = UTF32InSwap(utf32Pos);
-			if ( inUnit > 0xFFFF ) break;
-			*utf16Pos = UTF16Unit(inUnit);
-			++utf32Pos;
-			++utf16Pos;
-		}
-		utf32Left -= i;
-		utf16Left -= i;
-		
-		// Do a run of non-BMP, it copies 1 input unit into 2 output units.
-		while ( (utf32Left > 0) && (utf16Left > 0) ) {
-			size_t len;
-			UTF32Unit inUnit = UTF32InSwap(utf32Pos);
-			if ( inUnit <= 0xFFFF ) break;
-			CodePoint_to_UTF16Nat_Surrogate ( inUnit, utf16Pos, utf16Left, &len );
-			if ( len == 0 ) goto Done;	// Not enough room in the output buffer.
-			UC_Assert ( len == 2 );
-			utf32Left -= 1;
-			utf32Pos  += 1;
-			utf16Left -= 2;
-			utf16Pos  += 2;
-		}
-	
-	}
-	
-Done:	// Set the output lengths.
-	*utf32Read = utf32Len - utf32Left;
-	*utf16Written = utf16Len - utf16Left;
-	
-}	// UTF32Swp_to_UTF16Nat
-
-// =================================================================================================
diff --git a/xmpsdk/src/UnicodeConversions.hpp b/xmpsdk/src/UnicodeConversions.hpp
deleted file mode 100644
index 08883000..00000000
--- a/xmpsdk/src/UnicodeConversions.hpp
+++ /dev/null
@@ -1,121 +0,0 @@
-#ifndef __UnicodeConversions_h__
-#define __UnicodeConversions_h__
-
-// =================================================================================================
-// Copyright 2004-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include <string>
-
-// =================================================================================================
-
-#if UnicodeTestBuild
-	typedef unsigned char  UTF8Unit;
-	typedef unsigned short UTF16Unit;
-	typedef unsigned long  UTF32Unit;
-#else
-	typedef XMP_Uns8  UTF8Unit;
-	typedef XMP_Uns16 UTF16Unit;
-	typedef XMP_Uns32 UTF32Unit;
-#endif
-
-// -------------------------------------------------------------------------------------------------
-
-// ! The UTF16 and UTF32 counts are in storage units, not bytes! CodePoint values are always native.
-
-// *** MIght be better to return a status than throw an exception for errors?
-
-typedef void (*CodePoint_to_UTF16_Proc) ( const UTF32Unit cpIn, UTF16Unit * utf16Out, const size_t utf16Len, size_t * utf16Written );
-
-typedef void (*CodePoint_from_UTF16_Proc) ( const UTF16Unit * utf16In, const size_t utf16Len, UTF32Unit * cpOut, size_t * utf16Read );
-
-typedef void (*UTF8_to_UTF16_Proc)  ( const UTF8Unit *  utf8In,    const size_t utf8Len,
-				                      UTF16Unit *       utf16Out,  const size_t utf16Len,
-				                      size_t *          utf8Read,  size_t *     utf16Written );
-
-typedef void (*UTF8_to_UTF32_Proc)  ( const UTF8Unit *  utf8In,    const size_t utf8Len,
-				                      UTF32Unit *       utf32Out,  const size_t utf32Len,
-				                      size_t *          utf8Read,  size_t *     utf32Written );
-
-typedef void (*UTF16_to_UTF8_Proc)  ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				                      UTF8Unit *        utf8Out,   const size_t utf8Len,
-				                      size_t *          utf16Read, size_t *     utf8Written );
-
-typedef void (*UTF32_to_UTF8_Proc)  ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				                      UTF8Unit *        utf8Out,   const size_t utf8Len,
-				                      size_t *          utf32Read, size_t *     utf8Written );
-
-typedef void (*UTF16_to_UTF32_Proc) ( const UTF16Unit * utf16In,   const size_t utf16Len,
-				                      UTF32Unit *       utf32Out,  const size_t utf32Len,
-				                      size_t *          utf16Read, size_t *     utf32Written );
-
-typedef void (*UTF32_to_UTF16_Proc) ( const UTF32Unit * utf32In,   const size_t utf32Len,
-				                      UTF16Unit *       utf16Out,  const size_t utf16Len,
-				                      size_t *          utf32Read, size_t *     utf16Written );
-
-// -------------------------------------------------------------------------------------------------
-
-extern void CodePoint_to_UTF8 ( const UTF32Unit cpIn, UTF8Unit *  utf8Out,  const size_t utf8Len,  size_t * utf8Written );
-
-extern void CodePoint_from_UTF8 ( const UTF8Unit *  utf8In,  const size_t utf8Len,  UTF32Unit * cpOut, size_t * utf8Read );
-
-extern CodePoint_to_UTF16_Proc CodePoint_to_UTF16BE;
-extern CodePoint_to_UTF16_Proc CodePoint_to_UTF16LE;
-
-extern CodePoint_from_UTF16_Proc CodePoint_from_UTF16BE;
-extern CodePoint_from_UTF16_Proc CodePoint_from_UTF16LE;
-
-extern UTF8_to_UTF16_Proc  UTF8_to_UTF16BE;
-extern UTF8_to_UTF16_Proc  UTF8_to_UTF16LE;
-
-extern UTF8_to_UTF32_Proc  UTF8_to_UTF32BE;
-extern UTF8_to_UTF32_Proc  UTF8_to_UTF32LE;
-
-extern UTF16_to_UTF8_Proc  UTF16BE_to_UTF8;
-extern UTF16_to_UTF8_Proc  UTF16LE_to_UTF8;
-
-extern UTF32_to_UTF8_Proc  UTF32BE_to_UTF8;
-extern UTF32_to_UTF8_Proc  UTF32LE_to_UTF8;
-
-extern UTF8_to_UTF16_Proc  UTF8_to_UTF16Native;
-extern UTF8_to_UTF32_Proc  UTF8_to_UTF32Native;
-
-extern UTF16_to_UTF8_Proc  UTF16Native_to_UTF8;
-extern UTF32_to_UTF8_Proc  UTF32Native_to_UTF8;
-
-extern UTF16_to_UTF32_Proc UTF16BE_to_UTF32BE;
-extern UTF16_to_UTF32_Proc UTF16BE_to_UTF32LE;
-
-extern UTF16_to_UTF32_Proc UTF16LE_to_UTF32BE;
-extern UTF16_to_UTF32_Proc UTF16LE_to_UTF32LE;
-
-extern UTF32_to_UTF16_Proc UTF32BE_to_UTF16BE;
-extern UTF32_to_UTF16_Proc UTF32BE_to_UTF16LE;
-
-extern UTF32_to_UTF16_Proc UTF32LE_to_UTF16BE;
-extern UTF32_to_UTF16_Proc UTF32LE_to_UTF16LE;
-
-extern void SwapUTF16 ( const UTF16Unit * utf16In, UTF16Unit * utf16Out, const size_t utf16Len );
-extern void SwapUTF32 ( const UTF32Unit * utf32In, UTF32Unit * utf32Out, const size_t utf32Len );
-
-extern void ToUTF16 ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf16Str, bool bigEndian );
-extern void ToUTF32 ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf32Str, bool bigEndian );
-
-extern void FromUTF16 ( const UTF16Unit * utf16In, size_t utf16Len, std::string * utf8Str, bool bigEndian );
-extern void FromUTF32 ( const UTF32Unit * utf32In, size_t utf32Len, std::string * utf8Str, bool bigEndian );
-
-extern void ToUTF16Native ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf16Str );
-extern void ToUTF32Native ( const UTF8Unit * utf8In, size_t utf8Len, std::string * utf32Str );
-
-extern void FromUTF16Native ( const UTF16Unit * utf16In, size_t utf16Len, std::string * utf8Str );
-extern void FromUTF32Native ( const UTF32Unit * utf32In, size_t utf32Len, std::string * utf8Str );
-
-extern void InitializeUnicodeConversions();
-
-// =================================================================================================
-
-#endif	// __UnicodeConversions_h__
diff --git a/xmpsdk/src/UnicodeInlines.incl_cpp b/xmpsdk/src/UnicodeInlines.incl_cpp
deleted file mode 100644
index 8d55bad3..00000000
--- a/xmpsdk/src/UnicodeInlines.incl_cpp
+++ /dev/null
@@ -1,129 +0,0 @@
-#ifndef __UnicodeInlines_incl_cpp__
-#define __UnicodeInlines_incl_cpp__
-
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "UnicodeConversions.hpp"
-
-// =================================================================================================
-// Inner loop utilities that need to be inlined.
-// =================================================================================================
-
-static inline XMP_Uns32 GetCodePoint ( const XMP_Uns8 ** utf8Str_io )
-{
-	const XMP_Uns8 * u8Ptr = *utf8Str_io;
-	XMP_Uns32 cp;
-	size_t u8Len;
-	CodePoint_from_UTF8 ( u8Ptr, 4, &cp, &u8Len );	// Throws an exception for errors.
-	*utf8Str_io = u8Ptr + u8Len;
-	return cp;
-}
-
-// =================================================================================================
-
-static inline bool IsStartChar_ASCII ( XMP_Uns32 cp )
-{
-	// ASCII starting characters for an XML name.
-	if ( (('a' <= cp) && (cp <= 'z')) || (('A' <= cp) && (cp <= 'Z')) || (cp == '_') ) return true;
-	return false;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-static inline bool IsStartChar_NonASCII ( XMP_Uns32 cp )
-{
-	// Non-ASCII starting characters for an XML name.
-	
-	if ( ((0xC0 <= cp) && (cp <= 0xD6))  || ((0xD8 <= cp) && (cp <= 0xF6)) ) return true;
-	if ( ((0xF8 <= cp) && (cp <= 0x2FF)) || ((0x370 <= cp) && (cp <= 0x37D)) ) return true;
-
-	if ( ((0x37F <= cp) && (cp <= 0x1FFF))  || ((0x200C <= cp) && (cp <= 0x200D)) ) return true;
-	if ( ((0x2070 <= cp) && (cp <= 0x218F)) || ((0x2C00 <= cp) && (cp <= 0x2FEF)) ) return true;
-	if ( ((0x3001 <= cp) && (cp <= 0xD7FF)) || ((0xF900 <= cp) && (cp <= 0xFDCF)) ) return true;
-	if ( ((0xFDF0 <= cp) && (cp <= 0xFFFD)) || ((0x10000 <= cp) && (cp <= 0xEFFFF)) ) return true;
-
-	return false;
-
-}
-
-// -------------------------------------------------------------------------------------------------
-
-static inline bool IsOtherChar_ASCII ( XMP_Uns32 cp )
-{
-	// ASCII following characters for an XML name.
-	if ( (('0' <= cp) && (cp <= '9')) || (cp == '-') || (cp == '.') ) return true;
-	return false;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-static inline bool IsOtherChar_NonASCII ( XMP_Uns32 cp )
-{
-	// Non-ASCII following characters for an XML name.
-	if ( (cp == 0xB7) || ((0x300 <= cp) && (cp <= 0x36F))  || ((0x203F <= cp) && (cp <= 0x2040)) ) return true;
-	return false;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-static inline void VerifyUTF8 ( XMP_StringPtr str )
-{
-	const XMP_Uns8 * utf8Str = (XMP_Uns8*)str;
-	while ( *utf8Str != 0 ) {
-		while ( (*utf8Str != 0) && (*utf8Str < 0x80) ) ++utf8Str;
-		if ( *utf8Str >= 0x80 ) (void) GetCodePoint ( &utf8Str );	// Throws for bad UTF-8.
-	}
-}
-
-// -------------------------------------------------------------------------------------------------
-
-static inline void VerifySimpleXMLName ( XMP_StringPtr _nameStart, XMP_StringPtr _nameEnd )
-{
-
-	const XMP_Uns8 * nameStart = (const XMP_Uns8 *) _nameStart;
-	const XMP_Uns8 * nameEnd   = (const XMP_Uns8 *) _nameEnd;
-	const XMP_Uns8 * namePos   = nameStart;
-	XMP_Uns32 cp;
-	
-	// The first character is more restricted.
-	
-	if ( nameStart >= nameEnd ) XMP_Throw ( "Empty XML name", kXMPErr_BadXPath );
-
-	cp = *namePos;
-	if ( cp < 0x80 ) {
-		++namePos;
-		if ( ! IsStartChar_ASCII(cp) ) goto NameError;
-	} else {
-		cp = GetCodePoint ( &namePos );
-		if ( ! IsStartChar_NonASCII(cp) ) goto NameError;
-	}
-
-	// Check the rest of the name.
-	
-	while ( namePos < nameEnd ) {
-		cp = *namePos;
-		if ( cp < 0x80 ) {
-			++namePos;
-			if ( (! IsStartChar_ASCII(cp)) && (! IsOtherChar_ASCII(cp)) ) goto NameError;
-		} else {
-			cp = GetCodePoint ( &namePos );
-			if ( (! IsStartChar_NonASCII(cp)) && (! IsOtherChar_NonASCII(cp)) ) goto NameError;
-		}
-	}
-
-	return;
-
-NameError:
-	XMP_Throw ( "Bad XML name", kXMPErr_BadXPath );
-	
-}	// VerifySimpleXMLName
-
-// =================================================================================================
-
-#endif	// __UnicodeInlines_incl_cpp__
diff --git a/xmpsdk/src/WXMPIterator.cpp b/xmpsdk/src/WXMPIterator.cpp
deleted file mode 100644
index 4c47b0d3..00000000
--- a/xmpsdk/src/WXMPIterator.cpp
+++ /dev/null
@@ -1,188 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-
-#include "XMPIterator.hpp"
-#include "client-glue/WXMPIterator.hpp"
-
-#if XMP_WinBuild
-#   ifdef _MSC_VER
-        #pragma warning ( disable : 4101 ) // unreferenced local variable
-        #pragma warning ( disable : 4189 ) // local variable is initialized but not referenced
-        #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning)
-        #if XMP_DebugBuild
-            #pragma warning ( disable : 4297 ) // function assumed not to throw an exception but does
-#       endif
-#   endif
-#endif
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// =================================================================================================
-// CTor/DTor Wrappers
-// ==================
-
-void
-WXMPIterator_PropCTor_1 ( XMPMetaRef     xmpRef,
-                          XMP_StringPtr  schemaNS,
-                          XMP_StringPtr  propName,
-                          XMP_OptionBits options,
-                          WXMP_Result *  wResult )
-{
-    XMP_ENTER_WRAPPER ( "WXMPIterator_PropCTor_1" )
-
-		if ( schemaNS == 0 ) schemaNS = "";
-		if ( propName == 0 ) propName = "";
-
-		const XMPMeta & xmpObj = WtoXMPMeta_Ref ( xmpRef );
-		XMPIterator *   iter   = new XMPIterator ( xmpObj, schemaNS, propName, options );
-		++iter->clientRefs;
-		XMP_Assert ( iter->clientRefs == 1 );
-		wResult->ptrResult = XMPIteratorRef ( iter );
-
-    XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPIterator_TableCTor_1 ( XMP_StringPtr  schemaNS,
-                           XMP_StringPtr  propName,
-                           XMP_OptionBits options,
-                           WXMP_Result *  wResult )
-{
-    XMP_ENTER_WRAPPER ( "WXMPIterator_TableCTor_1" )
-
-		if ( schemaNS == 0 ) schemaNS = "";
-		if ( propName == 0 ) propName = "";
-
-		XMPIterator * iter = new XMPIterator ( schemaNS, propName, options );
-		++iter->clientRefs;
-		XMP_Assert ( iter->clientRefs == 1 );
-		wResult->ptrResult = XMPIteratorRef ( iter );
-
-    XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPIterator_IncrementRefCount_1 ( XMPIteratorRef iterRef )
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-	XMP_ENTER_WRAPPER ( "WXMPIterator_IncrementRefCount_1" )
-
-		XMPIterator * thiz = (XMPIterator*)iterRef;
-		
-		++thiz->clientRefs;
-		XMP_Assert ( thiz->clientRefs > 1 );
-
-	XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPIterator_DecrementRefCount_1 ( XMPIteratorRef iterRef )
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-	XMP_ENTER_WRAPPER ( "WXMPIterator_DecrementRefCount_1" )
-
-		XMPIterator * thiz = (XMPIterator*)iterRef;
-		
-		XMP_Assert ( thiz->clientRefs > 0 );
-		--thiz->clientRefs;
-		if ( thiz->clientRefs <= 0 ) delete ( thiz );
-
-	XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPIterator_Unlock_1 ( XMP_OptionBits options )
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-    XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPIterator_Unlock_1" )
-
-		XMPIterator::Unlock ( options );
-
-    XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// =================================================================================================
-// Class Method Wrappers
-// =====================
-
-void
-WXMPIterator_Next_1 ( XMPIteratorRef   iterRef,
-                      XMP_StringPtr *  schemaNS,
-                      XMP_StringLen *  nsSize,
-                      XMP_StringPtr *  propPath,
-                      XMP_StringLen *  pathSize,
-                      XMP_StringPtr *  propValue,
-                      XMP_StringLen *  valueSize,
-                      XMP_OptionBits * propOptions,
-                      WXMP_Result *    wResult )
-{
-    XMP_ENTER_WRAPPER ( "WXMPIterator_Next_1" )
-
-		if ( schemaNS == 0 ) schemaNS = &voidStringPtr;
-		if ( nsSize == 0 ) nsSize = &voidStringLen;
-		if ( propPath == 0 ) propPath = &voidStringPtr;
-		if ( pathSize == 0 ) pathSize = &voidStringLen;
-		if ( propValue == 0 ) propValue = &voidStringPtr;
-		if ( valueSize == 0 ) valueSize = &voidStringLen;
-		if ( propOptions == 0 ) propOptions = &voidOptionBits;
-
-		XMPIterator * iter = WtoXMPIterator_Ptr ( iterRef );
-		XMP_Bool found = iter->Next ( schemaNS, nsSize, propPath, pathSize, propValue, valueSize, propOptions );
-		wResult->int32Result = found;
-
-    XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPIterator_Skip_1 ( XMPIteratorRef iterRef,
-                      XMP_OptionBits options,
-                      WXMP_Result *  wResult )
-{
-    XMP_ENTER_WRAPPER ( "WXMPIterator_Skip_1" )
-
-		XMPIterator * iter = WtoXMPIterator_Ptr ( iterRef );
-		iter->Skip ( options );
-
-    XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_UnlockIter_1 ( XMPIteratorRef iterRef,
-                         XMP_OptionBits options )
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-    XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_UnlockIter_1" )
-
-		XMPIterator * iter = WtoXMPIterator_Ptr ( iterRef );
-		iter->UnlockIter ( options );
-
-    XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// =================================================================================================
-
-#if __cplusplus
-} /* extern "C" */
-#endif
diff --git a/xmpsdk/src/WXMPMeta.cpp b/xmpsdk/src/WXMPMeta.cpp
deleted file mode 100644
index 79692338..00000000
--- a/xmpsdk/src/WXMPMeta.cpp
+++ /dev/null
@@ -1,1310 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:	Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-
-#include "XMPMeta.hpp"
-#include "client-glue/WXMPMeta.hpp"
-
-#if XMP_WinBuild
-    #ifdef _MSC_VER
-        #pragma warning ( disable : 4101 ) // unreferenced local variable
-        #pragma warning ( disable : 4189 ) // local variable is initialized but not referenced
-        #pragma warning ( disable : 4702 ) // unreachable code
-        #pragma warning ( disable : 4800 ) // forcing value to bool 'true' or 'false' (performance warning)
-        #if XMP_DebugBuild
-            #pragma warning ( disable : 4297 ) // function assumed not to throw an exception but does
-        #endif
-    #endif
-#endif
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// =================================================================================================
-// Init/Term Wrappers
-// ==================
-
-/* class static */ void
-WXMPMeta_GetVersionInfo_1 ( XMP_VersionInfo * info )
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_GetVersionInfo_1" )
-
-		XMPMeta::GetVersionInfo ( info );
-
-	XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_Initialize_1 ( WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_Initialize_1" )
-
-		bool ok = XMPMeta::Initialize();
-		wResult->int32Result = ok;
-
-	XMP_EXIT_WRAPPER
-}
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_Terminate_1()
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_Terminate_1" )
-
-		XMPMeta::Terminate();
-
-	XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// =================================================================================================
-// CTor/DTor Wrappers
-// ==================
-
-void
-WXMPMeta_CTor_1 ( WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_CTor_1" )
-
-		XMPMeta * xmpObj = new XMPMeta();
-		++xmpObj->clientRefs;
-		XMP_Assert ( xmpObj->clientRefs == 1 );
-		wResult->ptrResult = XMPMetaRef ( xmpObj );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_IncrementRefCount_1 ( XMPMetaRef xmpRef )
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-	XMP_ENTER_WRAPPER ( "WXMPMeta_IncrementRefCount_1" )
-
-		XMPMeta * thiz = (XMPMeta*)xmpRef;
-		
-		++thiz->clientRefs;
-		XMP_Assert ( thiz->clientRefs > 0 );
-
-	XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_DecrementRefCount_1 ( XMPMetaRef xmpRef )
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DecrementRefCount_1" )
-
-		XMPMeta * thiz = (XMPMeta*)xmpRef;
-		
-		XMP_Assert ( thiz->clientRefs > 0 );
-		--thiz->clientRefs;
-		if ( thiz->clientRefs <= 0 ) delete ( thiz );
-
-	XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// =================================================================================================
-// Class Static Wrappers
-// =====================
-//
-// These are DLL-entry wrappers for class-static functions. They all follow a simple pattern:
-//
-//		try
-//			acquire toolbox lock
-//			validate parameters
-//			call through to the implementation
-//			retain toolbox lock if necessary
-//		catch anything and return an appropriate XMP_Error object
-//		return null (no error if we get to here)
-//
-// The toolbox lock is acquired through a local wrapper object that automatically unlocks when the
-// try-block is exited. The lock must be retained if the function is returning a string result. The
-// output string is owned by the toolkit, the client must copy the string then release the lock.
-// The lock used here is the overall toolkit lock. For simplicity at this time the lock is a simple
-// mutual exclusion lock, we do not allow multiple concurrent readers.
-//
-// The one exception to this model is UnlockToolkit. It does not acquire the toolkit lock since this
-// is the function the client calls to release the lock after copying an output string!
-//
-// =================================================================================================
-
-/* class static */ void
-WXMPMeta_GetGlobalOptions_1 ( WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetGlobalOptions_1" )
-
-		XMP_OptionBits options = XMPMeta::GetGlobalOptions();
-		wResult->int32Result = options;
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_SetGlobalOptions_1 ( XMP_OptionBits options,
-							  WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetGlobalOptions_1" )
-
-		XMPMeta::SetGlobalOptions ( options );
-
-	XMP_EXIT_WRAPPER
-}
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_DumpNamespaces_1 ( XMP_TextOutputProc outProc,
-							void *			   refCon,
-							WXMP_Result *	   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DumpNamespaces_1" )
-
-		if ( outProc == 0 ) XMP_Throw ( "Null client output routine", kXMPErr_BadParam );
-		
-		XMP_Status status = XMPMeta::DumpNamespaces ( outProc, refCon );
-		wResult->int32Result = status;
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_DumpAliases_1 ( XMP_TextOutputProc outProc,
-						 void *				refCon,
-						 WXMP_Result *		wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DumpAliases_1" )
-
-		if ( outProc == 0 ) XMP_Throw ( "Null client output routine", kXMPErr_BadParam );
-		
-		XMP_Status status = XMPMeta::DumpAliases ( outProc, refCon );
-		wResult->int32Result = status;
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_Unlock_1 ( XMP_OptionBits options )
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_Unlock_1" )
-
-		XMPMeta::Unlock ( options );
-
-	XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_RegisterNamespace_1 ( XMP_StringPtr   namespaceURI,
-                               XMP_StringPtr   prefix,
-                               WXMP_Result *   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_RegisterNamespace_1" )
-
-		if ( (namespaceURI == 0) || (*namespaceURI == 0) ) XMP_Throw ( "Empty namespace URI", kXMPErr_BadSchema );
-		if ( (prefix == 0) || (*prefix == 0) ) XMP_Throw ( "Empty prefix", kXMPErr_BadSchema );
-
-		XMPMeta::RegisterNamespace ( namespaceURI, prefix );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_GetNamespacePrefix_1 ( XMP_StringPtr	namespaceURI,
-								XMP_StringPtr * namespacePrefix,
-								XMP_StringLen * prefixSize,
-								WXMP_Result *	wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetNamespacePrefix_1" )
-
-		if ( (namespaceURI == 0) || (*namespaceURI == 0) ) XMP_Throw ( "Empty namespace URI", kXMPErr_BadSchema );
-
-		if ( namespacePrefix == 0 ) namespacePrefix = &voidStringPtr;
-		if ( prefixSize == 0 ) prefixSize = &voidStringLen;
-
-		bool found = XMPMeta::GetNamespacePrefix ( namespaceURI, namespacePrefix, prefixSize );
-		wResult->int32Result = found;
-		
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_GetNamespaceURI_1 ( XMP_StringPtr	 namespacePrefix,
-							 XMP_StringPtr * namespaceURI,
-							 XMP_StringLen * uriSize,
-							 WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetNamespaceURI_1" )
-
-		if ( (namespacePrefix == 0) || (*namespacePrefix == 0) ) XMP_Throw ( "Empty namespace prefix", kXMPErr_BadSchema );
-
-		if ( namespaceURI == 0 ) namespaceURI = &voidStringPtr;
-		if ( uriSize == 0 ) uriSize = &voidStringLen;
-	   
-		bool found = XMPMeta::GetNamespaceURI ( namespacePrefix, namespaceURI, uriSize );
-		wResult->int32Result = found;
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_DeleteNamespace_1 ( XMP_StringPtr namespaceURI,
-							 WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteNamespace_1" )
-
-		if ( (namespaceURI == 0) || (*namespaceURI == 0) ) XMP_Throw ( "Empty namespace URI", kXMPErr_BadSchema );
-
-		XMPMeta::DeleteNamespace ( namespaceURI );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_RegisterAlias_1 ( XMP_StringPtr  aliasNS,
-						   XMP_StringPtr  aliasProp,
-						   XMP_StringPtr  actualNS,
-						   XMP_StringPtr  actualProp,
-						   XMP_OptionBits arrayForm,
-						   WXMP_Result *  wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_RegisterAlias_1" )
-
-		if ( (aliasNS == 0) || (*aliasNS == 0) ) XMP_Throw ( "Empty alias namespace URI", kXMPErr_BadSchema );
-		if ( (aliasProp == 0) || (*aliasProp == 0) ) XMP_Throw ( "Empty alias property name", kXMPErr_BadXPath );
-		if ( (actualNS == 0) || (*actualNS == 0) ) XMP_Throw ( "Empty actual namespace URI", kXMPErr_BadSchema );
-		if ( (actualProp == 0) || (*actualProp == 0) ) XMP_Throw ( "Empty actual property name", kXMPErr_BadXPath );
-
-		XMPMeta::RegisterAlias ( aliasNS, aliasProp, actualNS, actualProp, arrayForm );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_ResolveAlias_1 ( XMP_StringPtr	   aliasNS,
-						  XMP_StringPtr	   aliasProp,
-						  XMP_StringPtr *  actualNS,
-						  XMP_StringLen *  nsSize,
-						  XMP_StringPtr *  actualProp,
-						  XMP_StringLen *  propSize,
-						  XMP_OptionBits * arrayForm,
-						  WXMP_Result *	   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_ResolveAlias_1" )
-	
-		if ( (aliasNS == 0) || (*aliasNS == 0) ) XMP_Throw ( "Empty alias namespace URI", kXMPErr_BadSchema );
-		if ( (aliasProp == 0) || (*aliasProp == 0) ) XMP_Throw ( "Empty alias property name", kXMPErr_BadXPath );
-	   
-		if ( actualNS == 0 ) actualNS = &voidStringPtr;
-		if ( nsSize == 0 ) nsSize = &voidStringLen;
-		if ( actualProp == 0 ) actualProp = &voidStringPtr;
-		if ( propSize == 0 ) propSize = &voidStringLen;
-		if ( arrayForm == 0 ) arrayForm = &voidOptionBits;
-		
-		bool found = XMPMeta::ResolveAlias ( aliasNS, aliasProp, actualNS, nsSize, actualProp, propSize, arrayForm );
-		wResult->int32Result = found;
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_DeleteAlias_1 ( XMP_StringPtr aliasNS,
-						 XMP_StringPtr aliasProp,
-						 WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteAlias_1" )
-
-		if ( (aliasNS == 0) || (*aliasNS == 0) ) XMP_Throw ( "Empty alias namespace URI", kXMPErr_BadSchema );
-		if ( (aliasProp == 0) || (*aliasProp == 0) ) XMP_Throw ( "Empty alias property name", kXMPErr_BadXPath );
-
-		XMPMeta::DeleteAlias ( aliasNS, aliasProp );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-/* class static */ void
-WXMPMeta_RegisterStandardAliases_1 ( XMP_StringPtr schemaNS,
-									 WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_RegisterStandardAliases_1" )
-
-		if ( schemaNS == 0 ) schemaNS = "";
-
-		XMPMeta::RegisterStandardAliases ( schemaNS );
-
-	XMP_EXIT_WRAPPER
-}
-
-// =================================================================================================
-// Class Method Wrappers
-// =====================
-//
-// These are DLL-entry wrappers for the methods. They all follow a simple pattern:
-//
-//		validate parameters
-//		try
-//			acquire object lock
-//			call through to the implementation
-//			retain object lock if necessary
-//		catch anything and return an appropriate XMP_Error object
-//		return null (no error if we get to here)
-//
-// The object lock is acquired through a local wrapper object that automatically unlocks when the
-// try-block is exited. The lock must be retained if the function is returning a string result. The
-// output string is owned by the object, the client must copy the string then release the lock. The
-// lock used here is the per-object lock. For simplicity at this time the lock is a simple mutual
-// exclusion lock, we do not allow multiple concurrent readers.
-//
-// The one exception to this model is UnlockObject. It does not acquire the object lock since this
-// is the function the client calls to release the lock after copying an output string!
-//
-// =================================================================================================
-
-void
-WXMPMeta_GetProperty_1 ( XMPMetaRef		  xmpRef,
-						 XMP_StringPtr	  schemaNS,
-						 XMP_StringPtr	  propName,
-						 XMP_StringPtr *  propValue,
-						 XMP_StringLen *  valueSize,
-						 XMP_OptionBits * options,
-						 WXMP_Result *	  wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_1" )
-	
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-		
-		if ( propValue == 0 ) propValue = &voidStringPtr;
-		if ( valueSize == 0 ) valueSize = &voidStringLen;
-		if ( options == 0 ) options = &voidOptionBits;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.GetProperty ( schemaNS, propName, propValue, valueSize, options );
-		wResult->int32Result = found;
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetArrayItem_1 ( XMPMetaRef	   xmpRef,
-						  XMP_StringPtr	   schemaNS,
-						  XMP_StringPtr	   arrayName,
-						  XMP_Index		   itemIndex,
-						  XMP_StringPtr *  itemValue,
-						  XMP_StringLen *  valueSize,
-						  XMP_OptionBits * options,
-						  WXMP_Result *	   wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetArrayItem_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-		
-		if ( itemValue == 0 ) itemValue = &voidStringPtr;
-		if ( valueSize == 0 ) valueSize = &voidStringLen;
-		if ( options == 0 ) options = &voidOptionBits;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.GetArrayItem ( schemaNS, arrayName, itemIndex, itemValue, valueSize, options );
-		wResult->int32Result = found;
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetStructField_1 ( XMPMetaRef		 xmpRef,
-							XMP_StringPtr	 schemaNS,
-							XMP_StringPtr	 structName,
-							XMP_StringPtr	 fieldNS,
-							XMP_StringPtr	 fieldName,
-							XMP_StringPtr *	 fieldValue,
-							XMP_StringLen *	 valueSize,
-							XMP_OptionBits * options,
-							WXMP_Result *	 wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetStructField_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath );
-		if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
-		if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
-		
-		if ( fieldValue == 0 ) fieldValue = &voidStringPtr;
-		if ( valueSize == 0 ) valueSize = &voidStringLen;
-		if ( options == 0 ) options = &voidOptionBits;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.GetStructField ( schemaNS, structName, fieldNS, fieldName, fieldValue, valueSize, options );
-		wResult->int32Result = found;
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetQualifier_1 ( XMPMetaRef	   xmpRef,
-						  XMP_StringPtr	   schemaNS,
-						  XMP_StringPtr	   propName,
-						  XMP_StringPtr	   qualNS,
-						  XMP_StringPtr	   qualName,
-						  XMP_StringPtr *  qualValue,
-						  XMP_StringLen *  valueSize,
-						  XMP_OptionBits * options,
-						  WXMP_Result *	   wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetQualifier_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-		if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema );
-		if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath );
-		
-		if ( qualValue == 0 ) qualValue = &voidStringPtr;
-		if ( valueSize == 0 ) valueSize = &voidStringLen;
-		if ( options == 0 ) options = &voidOptionBits;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.GetQualifier ( schemaNS, propName, qualNS, qualName, qualValue, valueSize, options );
-		wResult->int32Result = found;
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetProperty_1 ( XMPMetaRef		xmpRef,
-						 XMP_StringPtr	schemaNS,
-						 XMP_StringPtr	propName,
-						 XMP_StringPtr	propValue,
-						 XMP_OptionBits options,
-						 WXMP_Result *	wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetProperty ( schemaNS, propName, propValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetArrayItem_1 ( XMPMetaRef	 xmpRef,
-						  XMP_StringPtr	 schemaNS,
-						  XMP_StringPtr	 arrayName,
-						  XMP_Index		 itemIndex,
-						  XMP_StringPtr	 itemValue,
-						  XMP_OptionBits options,
-						  WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetArrayItem_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetArrayItem ( schemaNS, arrayName, itemIndex, itemValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_AppendArrayItem_1 ( XMPMetaRef		xmpRef,
-							 XMP_StringPtr	schemaNS,
-							 XMP_StringPtr	arrayName,
-							 XMP_OptionBits arrayOptions,
-							 XMP_StringPtr	itemValue,
-							 XMP_OptionBits options,
-							 WXMP_Result *	wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_AppendArrayItem_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->AppendArrayItem ( schemaNS, arrayName, arrayOptions, itemValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetStructField_1 ( XMPMetaRef	   xmpRef,
-							XMP_StringPtr  schemaNS,
-							XMP_StringPtr  structName,
-							XMP_StringPtr  fieldNS,
-							XMP_StringPtr  fieldName,
-							XMP_StringPtr  fieldValue,
-							XMP_OptionBits options,
-							WXMP_Result *  wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetStructField_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath );
-		if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
-		if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetStructField ( schemaNS, structName, fieldNS, fieldName, fieldValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetQualifier_1 ( XMPMetaRef	 xmpRef,
-						  XMP_StringPtr	 schemaNS,
-						  XMP_StringPtr	 propName,
-						  XMP_StringPtr	 qualNS,
-						  XMP_StringPtr	 qualName,
-						  XMP_StringPtr	 qualValue,
-						  XMP_OptionBits options,
-						  WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetQualifier_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-		if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema );
-		if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetQualifier ( schemaNS, propName, qualNS, qualName, qualValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_DeleteProperty_1 ( XMPMetaRef	  xmpRef,
-							XMP_StringPtr schemaNS,
-							XMP_StringPtr propName,
-							WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteProperty_1" )
- 
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->DeleteProperty ( schemaNS, propName );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_DeleteArrayItem_1 ( XMPMetaRef	   xmpRef,
-							 XMP_StringPtr schemaNS,
-							 XMP_StringPtr arrayName,
-							 XMP_Index	   itemIndex,
-							 WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteArrayItem_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->DeleteArrayItem ( schemaNS, arrayName, itemIndex );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_DeleteStructField_1 ( XMPMetaRef	 xmpRef,
-							   XMP_StringPtr schemaNS,
-							   XMP_StringPtr structName,
-							   XMP_StringPtr fieldNS,
-							   XMP_StringPtr fieldName,
-							   WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteStructField_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath );
-		if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
-		if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->DeleteStructField ( schemaNS, structName, fieldNS, fieldName );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_DeleteQualifier_1 ( XMPMetaRef	   xmpRef,
-							 XMP_StringPtr schemaNS,
-							 XMP_StringPtr propName,
-							 XMP_StringPtr qualNS,
-							 XMP_StringPtr qualName,
-							 WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DeleteQualifier_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-		if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema );
-		if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->DeleteQualifier ( schemaNS, propName, qualNS, qualName );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_DoesPropertyExist_1 ( XMPMetaRef	 xmpRef,
-							   XMP_StringPtr schemaNS,
-							   XMP_StringPtr propName,
-							   WXMP_Result * wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DoesPropertyExist_1" )
-	
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.DoesPropertyExist ( schemaNS, propName );
-		wResult->int32Result = found;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_DoesArrayItemExist_1 ( XMPMetaRef	  xmpRef,
-								XMP_StringPtr schemaNS,
-								XMP_StringPtr arrayName,
-								XMP_Index	  itemIndex,
-								WXMP_Result * wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DoesArrayItemExist_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.DoesArrayItemExist ( schemaNS, arrayName, itemIndex );
-		wResult->int32Result = found;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_DoesStructFieldExist_1 ( XMPMetaRef	xmpRef,
-								  XMP_StringPtr schemaNS,
-								  XMP_StringPtr structName,
-								  XMP_StringPtr fieldNS,
-								  XMP_StringPtr fieldName,
-								  WXMP_Result * wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DoesStructFieldExist_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath );
-		if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
-		if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.DoesStructFieldExist ( schemaNS, structName, fieldNS, fieldName );
-		wResult->int32Result = found;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_DoesQualifierExist_1 ( XMPMetaRef	  xmpRef,
-								XMP_StringPtr schemaNS,
-								XMP_StringPtr propName,
-								XMP_StringPtr qualNS,
-								XMP_StringPtr qualName,
-								WXMP_Result * wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DoesQualifierExist_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-		if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema );
-		if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath );
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.DoesQualifierExist ( schemaNS, propName, qualNS, qualName );
-		wResult->int32Result = found;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetLocalizedText_1 ( XMPMetaRef	   xmpRef,
-							  XMP_StringPtr	   schemaNS,
-							  XMP_StringPtr	   arrayName,
-							  XMP_StringPtr	   genericLang,
-							  XMP_StringPtr	   specificLang,
-							  XMP_StringPtr *  actualLang,
-							  XMP_StringLen *  langSize,
-							  XMP_StringPtr *  itemValue,
-							  XMP_StringLen *  valueSize,
-							  XMP_OptionBits * options,
-							  WXMP_Result *	   wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetLocalizedText_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-		if ( genericLang == 0 ) genericLang = "";
-		if ( (specificLang == 0) ||(*specificLang == 0) ) XMP_Throw ( "Empty specific language", kXMPErr_BadParam );
-		
-		if ( actualLang == 0 ) actualLang = &voidStringPtr;
-		if ( langSize == 0 ) langSize = &voidStringLen;
-		if ( itemValue == 0 ) itemValue = &voidStringPtr;
-		if ( valueSize == 0 ) valueSize = &voidStringLen;
-		if ( options == 0 ) options = &voidOptionBits;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.GetLocalizedText ( schemaNS, arrayName, genericLang, specificLang,
-											 actualLang, langSize, itemValue, valueSize, options );
-		wResult->int32Result = found;
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( found )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetLocalizedText_1 ( XMPMetaRef	 xmpRef,
-							  XMP_StringPtr	 schemaNS,
-							  XMP_StringPtr	 arrayName,
-							  XMP_StringPtr	 genericLang,
-							  XMP_StringPtr	 specificLang,
-							  XMP_StringPtr	 itemValue,
-							  XMP_OptionBits options,
-							  WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetLocalizedText_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-		if ( genericLang == 0 ) genericLang = "";
-		if ( (specificLang == 0) ||(*specificLang == 0) ) XMP_Throw ( "Empty specific language", kXMPErr_BadParam );
-		if ( itemValue == 0 ) itemValue = "";
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetLocalizedText ( schemaNS, arrayName, genericLang, specificLang, itemValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetProperty_Bool_1 ( XMPMetaRef	   xmpRef,
-							  XMP_StringPtr	   schemaNS,
-							  XMP_StringPtr	   propName,
-							  XMP_Bool *	   propValue,
-							  XMP_OptionBits * options,
-							  WXMP_Result *	   wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Bool_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		if ( propValue == 0 ) propValue = &voidByte;
-		if ( options == 0 ) options = &voidOptionBits;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool value;
-		bool found = meta.GetProperty_Bool ( schemaNS, propName, &value, options );
-		if ( propValue != 0 ) *propValue = value;
-		wResult->int32Result = found;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetProperty_Int_1 ( XMPMetaRef		  xmpRef,
-							 XMP_StringPtr	  schemaNS,
-							 XMP_StringPtr	  propName,
-							 XMP_Int32 *	  propValue,
-							 XMP_OptionBits * options,
-							 WXMP_Result *	  wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Int_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		if ( propValue == 0 ) propValue = &voidInt32;
-		if ( options == 0 ) options = &voidOptionBits;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.GetProperty_Int ( schemaNS, propName, propValue, options );
-		wResult->int32Result = found;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetProperty_Int64_1 ( XMPMetaRef		  xmpRef,
-							   XMP_StringPtr	  schemaNS,
-							   XMP_StringPtr	  propName,
-							   XMP_Int64 *	  propValue,
-							   XMP_OptionBits * options,
-							   WXMP_Result *	  wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Int64_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		if ( propValue == 0 ) propValue = &voidInt64;
-		if ( options == 0 ) options = &voidOptionBits;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.GetProperty_Int64 ( schemaNS, propName, propValue, options );
-		wResult->int32Result = found;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetProperty_Float_1 ( XMPMetaRef		xmpRef,
-							   XMP_StringPtr	schemaNS,
-							   XMP_StringPtr	propName,
-							   double *			propValue,
-							   XMP_OptionBits * options,
-							   WXMP_Result *	wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Float_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		if ( propValue == 0 ) propValue = &voidDouble;
-		if ( options == 0 ) options = &voidOptionBits;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.GetProperty_Float ( schemaNS, propName, propValue, options );
-		wResult->int32Result = found;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetProperty_Date_1 ( XMPMetaRef	   xmpRef,
-							  XMP_StringPtr	   schemaNS,
-							  XMP_StringPtr	   propName,
-							  XMP_DateTime *   propValue,
-							  XMP_OptionBits * options,
-							  WXMP_Result *	   wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetProperty_Date_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		if ( propValue == 0 ) propValue = &voidDateTime;
-		if ( options == 0 ) options = &voidOptionBits;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		bool found = meta.GetProperty_Date ( schemaNS, propName, propValue, options );
-		wResult->int32Result = found;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetProperty_Bool_1 ( XMPMetaRef	 xmpRef,
-							  XMP_StringPtr	 schemaNS,
-							  XMP_StringPtr	 propName,
-							  XMP_Bool		 propValue,
-							  XMP_OptionBits options,
-							  WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Bool_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetProperty_Bool ( schemaNS, propName, propValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetProperty_Int_1 ( XMPMetaRef		xmpRef,
-							 XMP_StringPtr	schemaNS,
-							 XMP_StringPtr	propName,
-							 XMP_Int32		propValue,
-							 XMP_OptionBits options,
-							 WXMP_Result *	wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Int_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetProperty_Int ( schemaNS, propName, propValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetProperty_Int64_1 ( XMPMetaRef	  xmpRef,
-							   XMP_StringPtr  schemaNS,
-							   XMP_StringPtr  propName,
-							   XMP_Int64	  propValue,
-							   XMP_OptionBits options,
-							   WXMP_Result *  wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Int64_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetProperty_Int64 ( schemaNS, propName, propValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetProperty_Float_1 ( XMPMetaRef	  xmpRef,
-							   XMP_StringPtr  schemaNS,
-							   XMP_StringPtr  propName,
-							   double		  propValue,
-							   XMP_OptionBits options,
-							   WXMP_Result *  wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Float_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetProperty_Float ( schemaNS, propName, propValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetProperty_Date_1 ( XMPMetaRef		   xmpRef,
-							  XMP_StringPtr		   schemaNS,
-							  XMP_StringPtr		   propName,
-							  const XMP_DateTime & propValue,
-							  XMP_OptionBits	   options,
-							  WXMP_Result *		   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetProperty_Date_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetProperty_Date ( schemaNS, propName, propValue, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_DumpObject_1 ( XMPMetaRef		   xmpRef,
-						XMP_TextOutputProc outProc,
-						void *			   refCon,
-						WXMP_Result *	   wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_DumpObject_1" )
-
-		if ( outProc == 0 ) XMP_Throw ( "Null client output routine", kXMPErr_BadParam );
-		
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		XMP_Status status = meta.DumpObject ( outProc, refCon );
-		wResult->int32Result = status;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_Sort_1 ( XMPMetaRef	xmpRef,
-				  WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_Sort_1" )
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->Sort();
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_Erase_1 ( XMPMetaRef	xmpRef,
-				   WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_Erase_1" )
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->Erase();
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_Clone_1 ( XMPMetaRef	  xmpRef,
-				   XMP_OptionBits options,
-				   WXMP_Result *  wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_Clone_1" )
-
-		const XMPMeta & xOriginal = WtoXMPMeta_Ref ( xmpRef );
-		XMPMeta * xClone = new XMPMeta;
-		xOriginal.Clone ( xClone, options );
-		XMP_Assert ( xClone->clientRefs == 0 );	// ! Gets incremented in TXMPMeta::Clone.
-		wResult->ptrResult = xClone;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_CountArrayItems_1 ( XMPMetaRef	   xmpRef,
-							 XMP_StringPtr schemaNS,
-							 XMP_StringPtr arrayName,
-							 WXMP_Result * wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_CountArrayItems_1" )
-		
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		XMP_Index count = meta.CountArrayItems ( schemaNS, arrayName );
-		wResult->int32Result = count;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_UnlockObject_1 ( XMPMetaRef	 xmpRef,
-						  XMP_OptionBits options ) /* const */
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPMeta_UnlockObject_1" )
-	
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		meta.UnlockObject ( options );
-
-	XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetObjectName_1 ( XMPMetaRef	   xmpRef,
-						   XMP_StringPtr * namePtr,
-						   XMP_StringLen * nameLen,
-						   WXMP_Result *   wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetObjectName_1" )
-
-		if ( namePtr == 0 ) namePtr = &voidStringPtr;
-		if ( nameLen == 0 ) nameLen = &voidStringLen;
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		meta.GetObjectName ( namePtr, nameLen );
-		
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) // ! Always keep the lock, a string is always returned!
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetObjectName_1 ( XMPMetaRef	 xmpRef,
-						   XMP_StringPtr name,
-						   WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetObjectName_1" )
-
-		if ( name == 0 ) name = "";
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetObjectName ( name );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_GetObjectOptions_1 ( XMPMetaRef    xmpRef,
-							  WXMP_Result * wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_GetObjectOptions_1" )
-
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		XMP_OptionBits options = meta.GetObjectOptions();
-		wResult->int32Result = options;
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SetObjectOptions_1 ( XMPMetaRef	 xmpRef,
-							  XMP_OptionBits options,
-							  WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SetObjectOptions_1" )
-	
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->SetObjectOptions ( options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_ParseFromBuffer_1 ( XMPMetaRef		xmpRef,
-							 XMP_StringPtr	buffer,
-							 XMP_StringLen	bufferSize,
-							 XMP_OptionBits options,
-							 WXMP_Result *	wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_ParseFromBuffer_1" )
-
-		XMPMeta * meta = WtoXMPMeta_Ptr ( xmpRef );
-		meta->ParseFromBuffer ( buffer, bufferSize, options );
-		
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPMeta_SerializeToBuffer_1 ( XMPMetaRef	   xmpRef,
-							   XMP_StringPtr * rdfString,
-							   XMP_StringLen * rdfSize,
-							   XMP_OptionBits  options,
-							   XMP_StringLen   padding,
-							   XMP_StringPtr   newline,
-							   XMP_StringPtr   indent,
-							   XMP_Index	   baseIndent,
-							   WXMP_Result *   wResult ) /* const */
-{
-	XMP_ENTER_WRAPPER ( "WXMPMeta_SerializeToBuffer_1" )
-
-		if ( rdfString == 0 ) rdfString = &voidStringPtr;
-		if ( rdfSize == 0 ) rdfSize = &voidStringLen;
-		
-		if ( newline == 0 ) newline = "";
-		if ( indent == 0 ) indent = "";
-		
-		const XMPMeta & meta = WtoXMPMeta_Ref ( xmpRef );
-		meta.SerializeToBuffer ( rdfString, rdfSize, options, padding, newline, indent, baseIndent );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true ) // ! Always keep the lock, a string is always returned!
-}
-
-// =================================================================================================
-
-#if __cplusplus
-} /* extern "C" */
-#endif
diff --git a/xmpsdk/src/WXMPUtils.cpp b/xmpsdk/src/WXMPUtils.cpp
deleted file mode 100644
index e3ce4375..00000000
--- a/xmpsdk/src/WXMPUtils.cpp
+++ /dev/null
@@ -1,626 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:	Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-// *** Should change "type * inParam" to "type & inParam"
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-
-#include "XMPUtils.hpp"
-#include "client-glue/WXMPUtils.hpp"
-
-#if XMP_WinBuild
-    #ifdef _MSC_VER
-        #pragma warning ( disable : 4101 ) // unreferenced local variable
-        #pragma warning ( disable : 4189 ) // local variable is initialized but not referenced
-        #pragma warning ( disable : 4800 )	// forcing value to bool 'true' or 'false' (performance warning)
-        #if XMP_DebugBuild
-            #pragma warning ( disable : 4297 ) // function assumed not to throw an exception but does
-        #endif
-    #endif
-#endif
-
-#if __cplusplus
-extern "C" {
-#endif
-
-// =================================================================================================
-// Class Static Wrappers
-// =====================
-
-void
-WXMPUtils_Unlock_1 ( XMP_OptionBits options )
-{
-	WXMP_Result * wResult = &void_wResult;	// ! Needed to "fool" the EnterWrapper macro.
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_Unlock_1" )
-
-		XMPUtils::Unlock ( options );
-
-	XMP_EXIT_WRAPPER_NO_THROW
-}
-
-// =================================================================================================
-
-void
-WXMPUtils_ComposeArrayItemPath_1 ( XMP_StringPtr   schemaNS,
-								   XMP_StringPtr   arrayName,
-								   XMP_Index	   itemIndex,
-								   XMP_StringPtr * fullPath,
-								   XMP_StringLen * pathSize,
-								   WXMP_Result *   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeArrayItemPath_1" )
-	
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-		
-		if ( fullPath == 0 ) fullPath = &voidStringPtr;
-		if ( pathSize == 0 ) pathSize = &voidStringLen;
-
-		XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, fullPath, pathSize );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ComposeStructFieldPath_1 ( XMP_StringPtr	 schemaNS,
-									 XMP_StringPtr	 structName,
-									 XMP_StringPtr	 fieldNS,
-									 XMP_StringPtr	 fieldName,
-									 XMP_StringPtr * fullPath,
-									 XMP_StringLen * pathSize,
-									 WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeStructFieldPath_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (structName == 0) || (*structName == 0) ) XMP_Throw ( "Empty struct name", kXMPErr_BadXPath );
-		if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
-		if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
-		
-		if ( fullPath == 0 ) fullPath = &voidStringPtr;
-		if ( pathSize == 0 ) pathSize = &voidStringLen;
-
-		XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, fullPath, pathSize );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ComposeQualifierPath_1 ( XMP_StringPtr   schemaNS,
-								   XMP_StringPtr   propName,
-								   XMP_StringPtr   qualNS,
-								   XMP_StringPtr   qualName,
-								   XMP_StringPtr * fullPath,
-								   XMP_StringLen * pathSize,
-								   WXMP_Result *   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeQualifierPath_1" )
-	
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (propName == 0) || (*propName == 0) ) XMP_Throw ( "Empty property name", kXMPErr_BadXPath );
-		if ( (qualNS == 0) || (*qualNS == 0) ) XMP_Throw ( "Empty qualifier namespace URI", kXMPErr_BadSchema );
-		if ( (qualName == 0) || (*qualName == 0) ) XMP_Throw ( "Empty qualifier name", kXMPErr_BadXPath );
-		
-		if ( fullPath == 0 ) fullPath = &voidStringPtr;
-		if ( pathSize == 0 ) pathSize = &voidStringLen;
-
-		XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, fullPath, pathSize );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ComposeLangSelector_1 ( XMP_StringPtr	  schemaNS,
-								  XMP_StringPtr	  arrayName,
-								  XMP_StringPtr	  langName,
-								  XMP_StringPtr * fullPath,
-								  XMP_StringLen * pathSize,
-								  WXMP_Result *	  wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeLangSelector_1" )
-	
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-		if ( (langName == 0) || (*langName == 0) ) XMP_Throw ( "Empty language name", kXMPErr_BadParam );
-		
-		if ( fullPath == 0 ) fullPath = &voidStringPtr;
-		if ( pathSize == 0 ) pathSize = &voidStringLen;
-
-		XMPUtils::ComposeLangSelector ( schemaNS, arrayName, langName, fullPath, pathSize );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ComposeFieldSelector_1 ( XMP_StringPtr   schemaNS,
-								   XMP_StringPtr   arrayName,
-								   XMP_StringPtr   fieldNS,
-								   XMP_StringPtr   fieldName,
-								   XMP_StringPtr   fieldValue,
-								   XMP_StringPtr * fullPath,
-								   XMP_StringLen * pathSize,
-								   WXMP_Result *   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_ComposeFieldSelector_1" )
-	
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-		if ( (fieldNS == 0) || (*fieldNS == 0) ) XMP_Throw ( "Empty field namespace URI", kXMPErr_BadSchema );
-		if ( (fieldName == 0) || (*fieldName == 0) ) XMP_Throw ( "Empty field name", kXMPErr_BadXPath );
-		if ( fieldValue == 0 ) fieldValue = "";
-		
-		if ( fullPath == 0 ) fullPath = &voidStringPtr;
-		if ( pathSize == 0 ) pathSize = &voidStringLen;
-
-		XMPUtils::ComposeFieldSelector ( schemaNS, arrayName, fieldNS, fieldName, fieldValue, fullPath, pathSize );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// =================================================================================================
-
-void
-WXMPUtils_ConvertFromBool_1 ( XMP_Bool		  binValue,
-							  XMP_StringPtr * strValue,
-							  XMP_StringLen * strSize,
-							  WXMP_Result *	  wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromBool_1" )
-
-		if ( strValue == 0 ) strValue = &voidStringPtr;
-		if ( strSize == 0 ) strSize = &voidStringLen;
-
-		XMPUtils::ConvertFromBool ( binValue, strValue, strSize );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ConvertFromInt_1 ( XMP_Int32		 binValue,
-							 XMP_StringPtr	 format,
-							 XMP_StringPtr * strValue,
-							 XMP_StringLen * strSize,
-							 WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromInt_1" )
-
-		if ( format == 0 ) format = "";
-		
-		if ( strValue == 0 ) strValue = &voidStringPtr;
-		if ( strSize == 0 ) strSize = &voidStringLen;
-
-		XMPUtils::ConvertFromInt ( binValue, format, strValue, strSize );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ConvertFromInt64_1 ( XMP_Int64	   binValue,
-							   XMP_StringPtr   format,
-							   XMP_StringPtr * strValue,
-							   XMP_StringLen * strSize,
-							   WXMP_Result *   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromInt64_1" )
-
-		if ( format == 0 ) format = "";
-		
-		if ( strValue == 0 ) strValue = &voidStringPtr;
-		if ( strSize == 0 ) strSize = &voidStringLen;
-
-		XMPUtils::ConvertFromInt64 ( binValue, format, strValue, strSize );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ConvertFromFloat_1 ( double		   binValue,
-							   XMP_StringPtr   format,
-							   XMP_StringPtr * strValue,
-							   XMP_StringLen * strSize,
-							   WXMP_Result *   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromFloat_1" )
-
-		if ( format == 0 ) format = "";
-		
-		if ( strValue == 0 ) strValue = &voidStringPtr;
-		if ( strSize == 0 ) strSize = &voidStringLen;
-
-		XMPUtils::ConvertFromFloat ( binValue, format, strValue, strSize );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ConvertFromDate_1 ( const XMP_DateTime & binValue,
-							  XMP_StringPtr *	   strValue,
-							  XMP_StringLen *	   strSize,
-							  WXMP_Result *		   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_ConvertFromDate_1" )
-
-		if ( strValue == 0 ) strValue = &voidStringPtr;
-		if ( strSize == 0 ) strSize = &voidStringLen;
-
-		XMPUtils::ConvertFromDate( binValue, strValue, strSize );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// =================================================================================================
-
-void
-WXMPUtils_ConvertToBool_1 ( XMP_StringPtr strValue,
-							WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToBool_1" )
-
-		if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam);
-		XMP_Bool result = XMPUtils::ConvertToBool ( strValue );
-		wResult->int32Result = result;
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ConvertToInt_1 ( XMP_StringPtr strValue,
-						   WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToInt_1" )
-
-		if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam);
-		XMP_Int32 result = XMPUtils::ConvertToInt ( strValue );
-		wResult->int32Result = result;
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ConvertToInt64_1 ( XMP_StringPtr strValue,
-						     WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToInt64_1" )
-
-		if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam);
-		XMP_Int64 result = XMPUtils::ConvertToInt64 ( strValue );
-		wResult->int64Result = result;
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ConvertToFloat_1 ( XMP_StringPtr strValue,
-							 WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToFloat_1")
-
-		if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty string value", kXMPErr_BadParam);
-		double result = XMPUtils::ConvertToFloat ( strValue );
-		wResult->floatResult = result;
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ConvertToDate_1 ( XMP_StringPtr  strValue,
-							XMP_DateTime * binValue,
-							WXMP_Result *  wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToDate_1" )
-
-		if ( binValue == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam); // ! Pointer is from the client.
-		XMPUtils::ConvertToDate ( strValue, binValue );
-
-	XMP_EXIT_WRAPPER
-}
-
-// =================================================================================================
-
-void
-WXMPUtils_CurrentDateTime_1 ( XMP_DateTime * time,
-							  WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_CurrentDateTime_1" )
-	
-		if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam);
-		XMPUtils::CurrentDateTime ( time );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_SetTimeZone_1 ( XMP_DateTime * time,
-						  WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_SetTimeZone_1" )
-
-		if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam);
-		XMPUtils::SetTimeZone ( time );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ConvertToUTCTime_1 ( XMP_DateTime * time,
-							   WXMP_Result *  wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToUTCTime_1" )
-
-		if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam);
-		XMPUtils::ConvertToUTCTime ( time );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_ConvertToLocalTime_1 ( XMP_DateTime * time,
-								 WXMP_Result *	wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_ConvertToLocalTime_1" )
-
-		if ( time == 0 ) XMP_Throw ( "Null output date", kXMPErr_BadParam);
-		XMPUtils::ConvertToLocalTime ( time );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_CompareDateTime_1 ( const XMP_DateTime & left,
-							  const XMP_DateTime & right,
-							  WXMP_Result *		   wResult )
-{
-	XMP_ENTER_WRAPPER_NO_LOCK ( "WXMPUtils_CompareDateTime_1" )
-
-		int result = XMPUtils::CompareDateTime ( left, right );
-		wResult->int32Result = result;
-
-	XMP_EXIT_WRAPPER
-}
-
-// =================================================================================================
-
-void
-WXMPUtils_EncodeToBase64_1 ( XMP_StringPtr	 rawStr,
-							 XMP_StringLen	 rawLen,
-							 XMP_StringPtr * encodedStr,
-							 XMP_StringLen * encodedLen,
-							 WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_EncodeToBase64_1" )
-	
-		if ( encodedStr == 0 ) encodedStr = &voidStringPtr;
-		if ( encodedLen == 0 ) encodedLen = &voidStringLen;
-
-		XMPUtils::EncodeToBase64 ( rawStr, rawLen, encodedStr, encodedLen );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_DecodeFromBase64_1 ( XMP_StringPtr   encodedStr,
-							   XMP_StringLen   encodedLen,
-							   XMP_StringPtr * rawStr,
-							   XMP_StringLen * rawLen,
-							   WXMP_Result *   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_DecodeFromBase64_1" )
-
-		if ( rawStr == 0 ) rawStr = &voidStringPtr;
-		if ( rawLen == 0 ) rawLen = &voidStringLen;
-
-		XMPUtils::DecodeFromBase64 ( encodedStr, encodedLen, rawStr, rawLen );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// =================================================================================================
-
-void
-WXMPUtils_PackageForJPEG_1 ( XMPMetaRef      wxmpObj,
-                             XMP_StringPtr * stdStr,
-                             XMP_StringLen * stdLen,
-                             XMP_StringPtr * extStr,
-                             XMP_StringLen * extLen,
-                             XMP_StringPtr * digestStr,
-                             XMP_StringLen * digestLen,
-                             WXMP_Result *   wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_PackageForJPEG_1" )
-
-		if ( stdStr == 0 ) stdStr = &voidStringPtr;
-		if ( stdLen == 0 ) stdLen = &voidStringLen;
-		if ( extStr == 0 ) extStr = &voidStringPtr;
-		if ( extLen == 0 ) extLen = &voidStringLen;
-		if ( digestStr == 0 ) digestStr = &voidStringPtr;
-		if ( digestLen == 0 ) digestLen = &voidStringLen;
-
-		const XMPMeta & xmpObj = WtoXMPMeta_Ref ( wxmpObj );
-		XMPUtils::PackageForJPEG ( xmpObj, stdStr, stdLen, extStr, extLen, digestStr, digestLen );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_MergeFromJPEG_1 ( XMPMetaRef    wfullXMP,
-                            XMPMetaRef    wextendedXMP,
-                            WXMP_Result * wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_MergeFromJPEG_1" )
-
-		if ( wfullXMP == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam );
-
-		XMPMeta * fullXMP = WtoXMPMeta_Ptr ( wfullXMP );
-		const XMPMeta & extendedXMP = WtoXMPMeta_Ref ( wextendedXMP );
-		XMPUtils::MergeFromJPEG ( fullXMP, extendedXMP );
-
-	XMP_EXIT_WRAPPER
-}
-
-// =================================================================================================
-
-void
-WXMPUtils_CatenateArrayItems_1 ( XMPMetaRef 	 wxmpObj,
-								 XMP_StringPtr	 schemaNS,
-								 XMP_StringPtr	 arrayName,
-								 XMP_StringPtr	 separator,
-								 XMP_StringPtr	 quotes,
-								 XMP_OptionBits	 options,
-								 XMP_StringPtr * catedStr,
-								 XMP_StringLen * catedLen,
-								 WXMP_Result *	 wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_CatenateArrayItems_1" )
-
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-		
-		if ( separator == 0 ) separator = "; ";
-		if ( quotes == 0 ) quotes = "\"";
-		
-		if ( catedStr == 0 ) catedStr = &voidStringPtr;
-		if ( catedLen == 0 ) catedLen = &voidStringLen;
-
-		const XMPMeta & xmpObj = WtoXMPMeta_Ref ( wxmpObj );
-		XMPUtils::CatenateArrayItems ( xmpObj, schemaNS, arrayName, separator, quotes, options, catedStr, catedLen );
-
-	XMP_EXIT_WRAPPER_KEEP_LOCK ( true )
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_SeparateArrayItems_1 ( XMPMetaRef 	wxmpObj,
-								 XMP_StringPtr	schemaNS,
-								 XMP_StringPtr	arrayName,
-								 XMP_OptionBits options,
-								 XMP_StringPtr	catedStr,
-								 WXMP_Result *	wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_SeparateArrayItems_1" )
-
-		if ( wxmpObj == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam );
-		if ( (schemaNS == 0) || (*schemaNS == 0) ) XMP_Throw ( "Empty schema namespace URI", kXMPErr_BadSchema );
-		if ( (arrayName == 0) || (*arrayName == 0) ) XMP_Throw ( "Empty array name", kXMPErr_BadXPath );
-		if ( catedStr == 0 ) catedStr = "";
-		
-		XMPMeta * xmpObj = WtoXMPMeta_Ptr ( wxmpObj );
-		XMPUtils::SeparateArrayItems ( xmpObj, schemaNS, arrayName, options, catedStr );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_RemoveProperties_1 ( XMPMetaRef 	  wxmpObj,
-							   XMP_StringPtr  schemaNS,
-							   XMP_StringPtr  propName,
-							   XMP_OptionBits options,
-							   WXMP_Result *  wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_RemoveProperties_1" )
-
-		if ( wxmpObj == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam );
-		if ( schemaNS == 0 ) schemaNS = "";
-		if ( propName == 0 ) propName = "";
-		
-		XMPMeta * xmpObj = WtoXMPMeta_Ptr ( wxmpObj );
-		XMPUtils::RemoveProperties ( xmpObj, schemaNS, propName, options );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_AppendProperties_1 ( XMPMetaRef     wSource,
-							   XMPMetaRef 	  wDest,
-							   XMP_OptionBits options,
-							   WXMP_Result *  wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_AppendProperties_1" )
-
-		if ( wDest == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam );
-
-		const XMPMeta & source = WtoXMPMeta_Ref ( wSource );
-		XMPMeta * dest = WtoXMPMeta_Ptr ( wDest );
-		XMPUtils::AppendProperties ( source, dest, options );
-
-	XMP_EXIT_WRAPPER
-}
-
-// -------------------------------------------------------------------------------------------------
-
-void
-WXMPUtils_DuplicateSubtree_1 ( XMPMetaRef     wSource,
-							   XMPMetaRef 	  wDest,
-							   XMP_StringPtr  sourceNS,
-							   XMP_StringPtr  sourceRoot,
-							   XMP_StringPtr  destNS,
-							   XMP_StringPtr  destRoot,
-							   XMP_OptionBits options,
-							   WXMP_Result *  wResult )
-{
-	XMP_ENTER_WRAPPER ( "WXMPUtils_DuplicateSubtree_1" )
-	
-		if ( wDest == 0 ) XMP_Throw ( "Output XMP pointer is null", kXMPErr_BadParam );
-		if ( (sourceNS == 0) || (*sourceNS == 0) ) XMP_Throw ( "Empty source schema URI", kXMPErr_BadSchema );
-		if ( (sourceRoot == 0) || (*sourceRoot == 0) ) XMP_Throw ( "Empty source root name", kXMPErr_BadXPath );
-		if ( destNS == 0 ) destNS = sourceNS;
-		if ( destRoot == 0 ) destRoot = sourceRoot;
-
-		const XMPMeta & source = WtoXMPMeta_Ref ( wSource );
-		XMPMeta * dest = WtoXMPMeta_Ptr ( wDest );
-		XMPUtils::DuplicateSubtree ( source, dest, sourceNS, sourceRoot, destNS, destRoot, options );
-
-	XMP_EXIT_WRAPPER
-}
-
-// =================================================================================================
-
-#if __cplusplus
-} /* extern "C" */
-#endif
diff --git a/xmpsdk/src/XMLParserAdapter.hpp b/xmpsdk/src/XMLParserAdapter.hpp
deleted file mode 100644
index 55d53cad..00000000
--- a/xmpsdk/src/XMLParserAdapter.hpp
+++ /dev/null
@@ -1,140 +0,0 @@
-#ifndef __XMLParserAdapter_hpp__
-#define __XMLParserAdapter_hpp__
-
-// =================================================================================================
-// Copyright 2005-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! Must be the first #include!
-#include "XMP_Const.h"
-
-#include <string>
-#include <vector>
-
-// =================================================================================================
-// XML_Node details
-//
-// The XML_Nodes are used only during the XML/RDF parsing process. This presently uses an XML parser
-// to create an XML tree, then a recursive descent RDF recognizer to build the corresponding XMP.
-// This makes it easier to swap XML parsers and provides a clean separation of XML and RDF issues.
-// The overall parsing would be faster and use less memory if the RDF recognition were done on the
-// fly using a state machine. But it was much easier to write the recursive descent version. The
-// current implementation is pretty fast in absolute terms, so being faster might not be crucial.
-//
-// Like the XMP tree, the XML tree contains vectors of pointers for down links, and offspring have
-// a pointer to their parent. Unlike the XMP tree, this is an exact XML document tree. There are no
-// introduced top level namespace nodes or rearrangement of the nodes..
-//
-// The exact state of namespaces can vary during the XML parsing, depending on the parser in use.
-// By the time the RDF recognition is done though, the namespaces must be normalized. All of the
-// used namespaces must be registered, this is done automatically if necessary. All of the "live"
-// namespace prefixes will be unique. The ns field of an XML_Node is the namespace URI, the name
-// field contains a qualified name (prefix:local). This includes default namespace mapping, the
-// URI and prefix will be missing only for elements and attributes in no namespace.
-
-class XML_Node;
-
-typedef XML_Node *	XML_NodePtr;	// Handy for things like: XML_Node * a, b; - b is XML_Node, not XML_Node*!
-
-enum { kRootNode = 0, kElemNode = 1, kAttrNode = 2, kCDataNode = 3, kPINode = 4 };
-
-#define IsWhitespaceChar(ch)	( ((ch) == ' ') || ((ch) == 0x09) || ((ch) == 0x0A) || ((ch) == 0x0D) )
-
-typedef std::vector<XML_NodePtr>		XML_NodeVector;
-typedef XML_NodeVector::iterator		XML_NodePos;
-typedef XML_NodeVector::const_iterator	XML_cNodePos;
-
-#if 0	// Pattern for iterating over the children or attributes:
-	for ( size_t xxNum = 0, xxLim = _node_->_offspring_.size(); xxNum < xxLim; ++xxNum ) {
-		const XML_NodePtr _curr_ = _node_->_offspring_[xxNum];
-	}
-#endif
-
-class XML_Node {
-public:
-
-	// Intended for lightweight internal use. Clients are expected to use the data directly.
-	
-	XMP_Uns8		kind;
-	std::string		ns, name, value;
-	size_t          nsPrefixLen;
-	XML_NodePtr		parent;
-	XML_NodeVector	attrs;
-	XML_NodeVector	content;
-	
-	bool IsWhitespaceNode() const;
-	bool IsLeafContentNode() const;	// An empty element or one with a single character data child node.
-	bool IsEmptyLeafNode() const;
-
-	XMP_StringPtr GetAttrValue ( XMP_StringPtr attrName ) const;
-	void SetAttrValue ( XMP_StringPtr attrName, XMP_StringPtr attrValue );
-
-	XMP_StringPtr GetLeafContentValue() const;
-	void SetLeafContentValue ( XMP_StringPtr value );
-	
-	size_t CountNamedElements ( XMP_StringPtr nsURI, XMP_StringPtr localName ) const;	// Number of child elements with this name.
-	XML_NodePtr GetNamedElement ( XMP_StringPtr nsURI, XMP_StringPtr localName, size_t which = 0 );
-	
-	void Dump ( std::string * buffer );
-	void Serialize ( std::string * buffer );
-	
-	void RemoveAttrs();
-	void RemoveContent();
-	void ClearNode();
-
-	XML_Node ( XML_NodePtr _parent, XMP_StringPtr _name, XMP_Uns8 _kind )
-            : kind(_kind), name(_name), nsPrefixLen(0), parent(_parent) {};
-
-	XML_Node ( XML_NodePtr _parent, const std::string & _name, XMP_Uns8 _kind )
-            : kind(_kind), name(_name), nsPrefixLen(0), parent(_parent) {};
-
-	virtual ~XML_Node() { RemoveAttrs(); RemoveContent(); };
-
-private:
-
-	XML_Node() : kind(0), parent(0)	{};	// ! Hidden to make sure parent pointer is always set.
-
-};
-
-// =================================================================================================
-// Abstract base class for XML parser adapters used by the XMP toolkit.
-
-enum { kXMLPendingInputMax = 16 };
-
-class XMLParserAdapter {
-public:
-
-	XMLParserAdapter()
-		: tree(0,"",kRootNode), rootNode(0), rootCount(0), charEncoding(XMP_OptionBits(-1)), pendingCount(0)
-	{
-		#if XMP_DebugBuild
-			parseLog = 0;
-		#endif
-	};
-
-	virtual ~XMLParserAdapter() {};
-	
-	virtual void ParseBuffer ( const void * buffer, size_t length, bool last ) = 0;
-
-	XML_Node		tree;
-	XML_NodeVector	parseStack;
-	XML_NodePtr		rootNode;
-	size_t			rootCount;
-
-	XMP_OptionBits	charEncoding;
-	size_t          pendingCount;
-	unsigned char	pendingInput[kXMLPendingInputMax];	// Buffered input for character encoding checks.
-	
-	#if XMP_DebugBuild
-		FILE * parseLog;
-	#endif
-
-};
-
-// =================================================================================================
-
-#endif	// __XMLParserAdapter_hpp__
diff --git a/xmpsdk/src/XML_Node.cpp b/xmpsdk/src/XML_Node.cpp
deleted file mode 100644
index 5f20358e..00000000
--- a/xmpsdk/src/XML_Node.cpp
+++ /dev/null
@@ -1,463 +0,0 @@
-// =================================================================================================
-// Copyright 2005-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! Must be the first #include!
-#include "XMLParserAdapter.hpp"
-
-#include <map>
-#include <cstring>
-#include <cstdio>
-
-// ! Can't include XMP..._Impl.hpp - used by both Core and Files.
-#define XMP_LitNMatch(s,l,n)	(std::strncmp((s),(l),(n)) == 0)
-
-#if XMP_WinBuild
-#ifdef _MSC_VER
-	#define snprintf _snprintf
-	#pragma warning ( disable : 4996 )	// snprintf is safe
-#endif
-#endif
-
-// =================================================================================================
-
-#if 0	// Pattern for iterating over the children or attributes:
-	for ( size_t xxNum = 0, xxLim = _node_->_offspring_->size(); xxNum < xxLim; ++xxNum ) {
-		const XML_NodePtr _curr_ = _node_->_offspring_[xxNum];
-	}
-#endif
-
-// =================================================================================================
-// XML_Node::IsWhitespaceNode
-//===========================
-
-bool XML_Node::IsWhitespaceNode() const
-{
-	if ( this->kind != kCDataNode ) return false;
-
-	for ( size_t i = 0; i < this->value.size(); ++i ) {
-		unsigned char ch = this->value[i];
-		if ( IsWhitespaceChar ( ch ) ) continue;
-		// *** Add checks for other whitespace characters.
-		return false;	// All the checks failed, this isn't whitespace.
-	}
-
-	return true;
-
-}	// XML_Node::IsWhitespaceNode
-
-// =================================================================================================
-// XML_Node::IsLeafContentNode
-//============================
-
-bool XML_Node::IsLeafContentNode() const
-{
-	if ( this->kind != kElemNode ) return false;
-	if ( this->content.size() == 0 ) return true;
-	if ( this->content.size() > 1 ) return false;
-	if ( this->content[0]->kind != kCDataNode ) return false;
-
-	return true;
-
-}	// XML_Node::IsLeafContentNode
-
-// =================================================================================================
-// XML_Node::IsEmptyLeafNode
-//==========================
-
-bool XML_Node::IsEmptyLeafNode() const
-{
-
-	if ( (this->kind != kElemNode) || (this->content.size() != 0) ) return false;
-	return true;
-
-}	// XML_Node::IsEmptyLeafNode
-
-// =================================================================================================
-// XML_Node::GetAttrValue
-//=======================
-
-XMP_StringPtr XML_Node::GetAttrValue ( XMP_StringPtr attrName ) const
-{
-
-	for ( size_t i = 0, aLim = this->attrs.size(); i < aLim; ++i ) {
-		XML_Node * attrPtr = this->attrs[i];
-		if ( ! attrPtr->ns.empty() ) continue;	// This form of GetAttrValue is for attrs in no namespace.
-		if ( attrPtr->name == attrName ) return attrPtr->value.c_str();
-	}
-	
-	return 0;	// Not found.
-
-}	// XML_Node::GetAttrValue
-
-// =================================================================================================
-// XML_Node::SetAttrValue
-//=======================
-
-void XML_Node::SetAttrValue ( XMP_StringPtr attrName, XMP_StringPtr attrValue )
-{
-	
-	for ( size_t i = 0, aLim = this->attrs.size(); i < aLim; ++i ) {
-		XML_Node * attrPtr = this->attrs[i];
-		if ( ! attrPtr->ns.empty() ) continue;	// This form of SetAttrValue is for attrs in no namespace.
-		if ( attrPtr->name == attrName ) {
-			attrPtr->value = attrValue;
-			return;
-		}
-	}
-
-}	// XML_Node::SetAttrValue
-
-// =================================================================================================
-// XML_Node::GetLeafContentValue
-//==============================
-
-XMP_StringPtr XML_Node::GetLeafContentValue() const
-{
-	if ( (! this->IsLeafContentNode()) || this->content.empty() ) return "";
-
-	return this->content[0]->value.c_str();
-
-}	// XML_Node::GetLeafContentValue
-
-// =================================================================================================
-// XML_Node::SetLeafContentValue
-//==============================
-
-void XML_Node::SetLeafContentValue ( XMP_StringPtr newValue )
-{
-	XML_Node * valueNode;
-	
-	if ( ! this->content.empty() ) {
-		valueNode = this->content[0];
-	} else {
-		valueNode = new XML_Node ( this, "", kCDataNode );
-		this->content.push_back ( valueNode );
-	}
-
-	valueNode->value = newValue;
-
-}	// XML_Node::SetLeafContentValue
-
-// =================================================================================================
-// XML_Node::CountNamedElements
-//=============================
-
-size_t XML_Node::CountNamedElements ( XMP_StringPtr nsURI, XMP_StringPtr localName ) const
-{
-	size_t count = 0;
-	
-	for ( size_t i = 0, vLim = this->content.size(); i < vLim; ++i ) {
-		const XML_Node & child = *this->content[i];
-		if ( child.ns != nsURI ) continue;
-		if ( strcmp ( localName, child.name.c_str()+child.nsPrefixLen ) != 0 ) continue;
-		++count;
-	}
-	
-	return count;
-	
-}	// XML_Node::CountNamedElements
-
-// =================================================================================================
-// XML_Node::GetNamedElement
-//==========================
-
-XML_NodePtr XML_Node::GetNamedElement ( XMP_StringPtr nsURI, XMP_StringPtr localName, size_t which /* = 0 */ )
-{
-
-	for ( size_t i = 0, vLim = this->content.size(); i < vLim; ++i ) {
-		XML_Node * childPtr = this->content[i];
-		if ( childPtr->ns != nsURI ) continue;
-		if ( strcmp ( localName, childPtr->name.c_str()+childPtr->nsPrefixLen ) != 0 ) continue;
-		if ( which == 0 ) return childPtr;
-		--which;
-	}
-	
-	return 0;	/// Not found.
-
-}	// XML_Node::GetNamedElement
-
-// =================================================================================================
-// DumpNodeList
-// ============
-
-static const char * kNodeKinds[] = { "root", "elem", "attr", "cdata", "pi" };
-
-static void DumpNodeList ( std::string * buffer, const XML_NodeVector & list, int indent )
-{
-
-	for ( size_t i = 0, limit = list.size(); i < limit; ++i ) {
-
-		const XML_Node * node = list[i];
-		
-		for ( int t = indent; t > 0; --t ) *buffer += "  ";
-		if ( node->IsWhitespaceNode() ) {
-			*buffer += "-- whitespace --\n";
-			continue;
-		}
-
-		*buffer += node->name;
-		*buffer += " - ";
-		*buffer += kNodeKinds[node->kind];
-		if ( ! node->value.empty() ) {
-			*buffer += ", value=\"";
-			*buffer += node->value;
-			*buffer += "\"";
-		}
-		if ( ! node->ns.empty() ) {
-			*buffer += ", ns=\"";
-			*buffer += node->ns;
-			*buffer += "\"";
-		}
-		if ( node->nsPrefixLen != 0 ) {
-			*buffer += ", prefixLen=";
-			char numBuf [20];
-			snprintf ( numBuf, sizeof(numBuf), "%lu", (unsigned long)node->nsPrefixLen );
-			*buffer += numBuf;
-		}
-		*buffer += "\n";
-	
-		if ( ! node->attrs.empty() ) {
-			for ( int t = indent+1; t > 0; --t ) *buffer += "  ";
-			*buffer += "attrs:\n";
-			DumpNodeList ( buffer, node->attrs, indent+2 );
-		}
-		
-		if ( ! node->content.empty() ) {
-			DumpNodeList ( buffer, node->content, indent+1 );
-		}
-
-	}
-
-}	// DumpNodeList
-
-// =================================================================================================
-// XML_Node::Dump
-//===============
-
-void XML_Node::Dump ( std::string * buffer )
-{
-
-	*buffer = "Dump of XML_Node tree\n";
-
-	*buffer += "Root info: name=\"";
-	*buffer += this->name;
-	*buffer += "\", value=\"";
-	*buffer += this->value;
-	*buffer += "\", ns=\"";
-	*buffer += this->ns;
-	*buffer += "\", kind=";
-	*buffer += kNodeKinds[this->kind];
-	*buffer += "\n";
-	
-	if ( ! this->attrs.empty() ) {
-		*buffer += "  attrs:\n";
-		DumpNodeList ( buffer, this->attrs, 2 );
-	}
-	*buffer += "\n";
-	
-	DumpNodeList ( buffer, this->content, 0 );
-
-}	// XML_Node::Dump
-
-// =================================================================================================
-// SerializeOneNode
-// ================
-
-static void SerializeOneNode ( std::string * buffer, const XML_Node & node )
-{
-	size_t i, limit;
-	XMP_StringPtr namePtr = node.name.c_str();
-	if ( XMP_LitNMatch ( namePtr, "_dflt_:", 7 ) ) namePtr += 7;	// Hack for default namespaces.
-
-	switch ( node.kind ) {
-	
-		case kElemNode:
-			*buffer += '<';
-			*buffer += namePtr;
-			for ( i = 0, limit = node.attrs.size(); i < limit; ++i ) {
-				SerializeOneNode ( buffer, *node.attrs[i] );
-			}
-			if ( node.content.empty() ) {
-				*buffer += "/>";
-			} else {
-				*buffer += '>';
-				for ( i = 0, limit = node.content.size(); i < limit; ++i ) {
-					SerializeOneNode ( buffer, *node.content[i] );
-				}
-				*buffer += "</";
-				*buffer += namePtr;
-				*buffer += '>';
-			}
-			break;
-	
-		case kAttrNode:
-			*buffer += ' ';
-			*buffer += namePtr;
-			*buffer += "=\"";
-			*buffer += node.value;
-			*buffer += '"';
-			break;
-	
-		case kCDataNode:
-			*buffer += node.value;
-			break;
-	
-		case kPINode:
-			*buffer += node.value;	// *** Note that we're dropping PIs during the Expat parse.
-			break;
-	
-	}
-
-}	// SerializeOneNode
-
-// =================================================================================================
-// CollectNamespaceDecls
-// =====================
-
-typedef std::map < std::string, std::string > NamespaceMap;
-
-static void CollectNamespaceDecls ( NamespaceMap * nsMap, const XML_Node & node )
-{
-	size_t i, limit;
-
-	if ( ! node.ns.empty() ) {
-		size_t nameMid = 0;
-		while ( node.name[nameMid] != ':' ) ++nameMid;
-		std::string prefix = node.name.substr ( 0, nameMid );
-		(*nsMap)[prefix] = node.ns;
-	}
-	
-	if ( node.kind == kElemNode ) {
-
-		for ( i = 0, limit = node.attrs.size(); i < limit; ++i ) {
-			CollectNamespaceDecls ( nsMap, *node.attrs[i] );
-		}
-
-		for ( i = 0, limit = node.content.size(); i < limit; ++i ) {
-			const XML_Node & content = *node.content[i];
-			if ( content.kind == kElemNode ) CollectNamespaceDecls ( nsMap, content );
-		}
-
-	}
-	
-}	// CollectNamespaceDecls
-
-// =================================================================================================
-// XML_Node::Serialize
-//====================
-
-void XML_Node::Serialize ( std::string * buffer )
-{
-	buffer->erase();
-	
-	if ( this->kind != kRootNode ) {
-
-		SerializeOneNode ( buffer, *this );
-
-	} else {
-	
-		// Do the outermost level here, in order to add the XML version and namespace declarations.
-
-		*buffer += "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
-
-		for ( size_t outer = 0, oLimit = this->content.size(); outer < oLimit; ++outer ) {
-
-			const XML_Node & node = *this->content[outer];
-
-			if ( node.kind != kElemNode ) {
-
-				SerializeOneNode ( buffer, node );
-
-			} else {
-
-				XMP_StringPtr namePtr = node.name.c_str();
-				if ( XMP_LitNMatch ( namePtr, "_dflt_:", 7 ) ) namePtr += 7;	// Hack for default namespaces.
-
-				*buffer += '<';
-				*buffer += namePtr;
-				
-				NamespaceMap nsMap;
-				CollectNamespaceDecls ( &nsMap, node );
-				NamespaceMap::iterator nsDecl = nsMap.begin();
-				NamespaceMap::iterator nsEnd  = nsMap.end();
-				for ( ; nsDecl != nsEnd; ++nsDecl ) {
-					const std::string & prefix = nsDecl->first;
-					*buffer += " xmlns";
-					if ( prefix != "_dflt_" ) { *buffer += ':'; *buffer += prefix; }
-					*buffer += "=\"";
-					*buffer += nsDecl->second;
-					*buffer += '"';
-				}
-
-				for ( size_t attr = 0, aLimit = node.attrs.size(); attr < aLimit; ++attr ) {
-					SerializeOneNode ( buffer, *node.attrs[attr] );
-				}
-
-				if ( node.content.empty() ) {
-					*buffer += "/>";
-				} else {
-					*buffer += '>';
-					for ( size_t child = 0, cLimit = node.content.size(); child < cLimit; ++child ) {
-						SerializeOneNode ( buffer, *node.content[child] );
-					}
-					*buffer += "</";
-					*buffer += namePtr;
-					*buffer += '>';
-				}
-
-			}
-
-		}
-		
-	}
-	
-
-}	// XML_Node::Serialize
-
-// =================================================================================================
-// XML_Node::RemoveAttrs
-//======================
-
-void XML_Node::RemoveAttrs()
-{
-
-	for ( size_t i = 0, vLim = this->attrs.size(); i < vLim; ++i ) delete this->attrs[i];
-	this->attrs.clear();
-
-}	// XML_Node::RemoveAttrs
-
-// =================================================================================================
-// XML_Node::RemoveContent
-//========================
-
-void XML_Node::RemoveContent()
-{
-
-	for ( size_t i = 0, vLim = this->content.size(); i < vLim; ++i ) delete this->content[i];
-	this->content.clear();
-
-}	// XML_Node::RemoveContent
-
-// =================================================================================================
-// XML_Node::ClearNode
-//====================
-
-void XML_Node::ClearNode()
-{
-
-	this->kind = 0;
-	this->ns.erase();
-	this->name.erase();
-	this->value.erase();
-
-	this->RemoveAttrs();
-	this->RemoveContent();
-
-}	// XML_Node::ClearNode
-
-// =================================================================================================
diff --git a/xmpsdk/src/XMPCore_Impl.cpp b/xmpsdk/src/XMPCore_Impl.cpp
deleted file mode 100644
index e3632b98..00000000
--- a/xmpsdk/src/XMPCore_Impl.cpp
+++ /dev/null
@@ -1,1468 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMP_Version.h"
-#include "XMPCore_Impl.hpp"
-#include "XMPMeta.hpp"	// *** For use of GetNamespacePrefix in FindSchemaNode.
-
-#include "UnicodeInlines.incl_cpp"
-
-#include <algorithm>
-
-using namespace std;
-
-#if XMP_WinBuild
-    #ifdef _MSC_VER
-        #pragma warning ( disable : 4290 )	// C++ exception specification ignored except ... not __declspec(nothrow)
-        #pragma warning ( disable : 4800 )	// forcing value to bool 'true' or 'false' (performance warning)
-    #endif
-#endif
-
-// *** Add debug codegen checks, e.g. that typical masking operations really work
-// *** Make option constants 0x...UL.
-
-// Internal code should be using #if with XMP_MacBuild, XMP_WinBuild, or XMP_UNIXBuild.
-// This is a sanity check in case of accidental use of *_ENV. Some clients use the poor
-// practice of defining the *_ENV macro with an empty value.
-#if defined ( MAC_ENV )
-	#if ! MAC_ENV
-		#error "MAC_ENV must be defined so that \"#if MAC_ENV\" is true"
-	#endif
-#elif defined ( WIN_ENV )
-	#if ! WIN_ENV
-		#error "WIN_ENV must be defined so that \"#if WIN_ENV\" is true"
-	#endif
-#elif defined ( UNIX_ENV )
-	#if ! UNIX_ENV
-		#error "UNIX_ENV must be defined so that \"#if UNIX_ENV\" is true"
-	#endif
-#endif
-
-// =================================================================================================
-// Static Variables
-// ================
-
-XMP_Int32 sXMP_InitCount = 0;
-
-XMP_StringMap *	sNamespaceURIToPrefixMap = 0;
-XMP_StringMap *	sNamespacePrefixToURIMap = 0;
-
-XMP_AliasMap *	sRegisteredAliasMap = 0;	// Needed by XMPIterator.
-
-XMP_VarString *	sOutputNS  = 0;
-XMP_VarString *	sOutputStr = 0;
-XMP_VarString * sExceptionMessage = 0;
-
-XMP_Mutex sXMPCoreLock;
-int sLockCount = 0;
-
-#if TraceXMPCalls
-	FILE * xmpOut = stderr;
-#endif
-
-void *              voidVoidPtr    = 0;	// Used to backfill null output parameters.
-XMP_StringPtr		voidStringPtr  = 0;
-XMP_StringLen		voidStringLen  = 0;
-XMP_OptionBits		voidOptionBits = 0;
-XMP_Uns8			voidByte       = 0;
-bool				voidBool       = 0;
-XMP_Int32			voidInt32      = 0;
-XMP_Int64			voidInt64      = 0;
-double				voidDouble     = 0.0;
-XMP_DateTime		voidDateTime;
-WXMP_Result 		void_wResult;
-
-// =================================================================================================
-// Mutex Utilities
-// ===============
-
-// ! Note that the mutex need not be "recursive", allowing the same thread to acquire it multiple
-// ! times. There is a single XMP lock which is acquired in the wrapper classes. Internal calls
-// ! never go back out to the wrappers.
-
-#if XMP_WinBuild
-
-	bool XMP_InitMutex ( XMP_Mutex * mutex ) {
-		InitializeCriticalSection ( mutex );
-		return true;
-	}
-	
-	void XMP_TermMutex ( XMP_Mutex & mutex ) {
-		DeleteCriticalSection ( &mutex );
-	}
-
-	void XMP_EnterCriticalRegion ( XMP_Mutex & mutex ) {
-		EnterCriticalSection ( &mutex );
-	}
-	
-	void XMP_ExitCriticalRegion ( XMP_Mutex & mutex ) {
-		LeaveCriticalSection ( &mutex );
-	}
-
-#else
-
-	// Use pthread for both Mac and generic UNIX.
-	// ! Would be nice to specify PTHREAD_MUTEX_ERRORCHECK, but the POSIX documentation is useless.
-	// ! Would be OK but overkill to specify PTHREAD_MUTEX_RECURSIVE.
-
-	bool XMP_InitMutex ( XMP_Mutex * mutex ) {
-		int err = pthread_mutex_init ( mutex, 0 );
-		return (err == 0 );
-	}
-	
-	void XMP_TermMutex ( XMP_Mutex & mutex ) {
-		(void) pthread_mutex_destroy ( &mutex );
-	}
-
-	void XMP_EnterCriticalRegion ( XMP_Mutex & mutex ) {
-		int err = pthread_mutex_lock ( &mutex );
-		if ( err != 0 ) XMP_Throw ( "XMP_EnterCriticalRegion - pthread_mutex_lock failure", kXMPErr_ExternalFailure );
-	}
-	
-	void XMP_ExitCriticalRegion ( XMP_Mutex & mutex ) {
-		int err = pthread_mutex_unlock ( &mutex );
-		if ( err != 0 ) XMP_Throw ( "XMP_ExitCriticalRegion - pthread_mutex_unlock failure", kXMPErr_ExternalFailure );
-	}
-
-#endif
-
-// =================================================================================================
-// Local Utilities
-// ===============
-
-// -------------------------------------------------------------------------------------------------
-// VerifyXPathRoot
-// ---------------
-//
-// Set up the first 2 components of the expanded XPath. Normalizes the various cases of using the
-// full schema URI and/or a qualified root property name. Returns true for normal processing. If
-// allowUnknownSchemaNS is true and the schema namespace is not registered, false is returned. If
-// allowUnknownSchemaNS is false and the schema namespace is not registered, an exception is thrown.
-
-// *** Should someday check the full syntax.
-
-static void
-VerifyXPathRoot	( XMP_StringPtr			schemaURI,
-				  XMP_StringPtr			propName,
-				  XMP_ExpandedXPath *	expandedXPath )
-{
-	// Do some basic checks on the URI and name. Try to lookup the URI. See if the name is qualified.
-	
-	XMP_Assert ( (schemaURI != 0) && (propName != 0) && (*propName != 0) );
-	XMP_Assert ( (expandedXPath != 0) && (expandedXPath->empty()) );
-
-	if ( *schemaURI == 0 ) XMP_Throw ( "Schema namespace URI is required", kXMPErr_BadSchema );
-
-	if ( (*propName == '?') || (*propName == '@') ) {
-		XMP_Throw ( "Top level name must not be a qualifier", kXMPErr_BadXPath );
-	}
-	for ( XMP_StringPtr ch = propName; *ch != 0; ++ch ) {
-		if ( (*ch == '/') || (*ch == '[') ) {
-			XMP_Throw ( "Top level name must be simple", kXMPErr_BadXPath );
-		}
-	}
-
-	XMP_StringMapPos uriPos = sNamespaceURIToPrefixMap->find ( XMP_VarString ( schemaURI ) );
-	if ( uriPos == sNamespaceURIToPrefixMap->end() ) {
-		XMP_Throw ( "Unregistered schema namespace URI", kXMPErr_BadSchema );
-	}
-
-	XMP_StringPtr colonPos = propName;
-	while ( (*colonPos != 0) && (*colonPos != ':') ) ++colonPos;
-	VerifySimpleXMLName ( propName, colonPos );	// Verify the part before any colon.
-
-	// Verify the various URI and prefix combinations. Initialize the expanded XPath.
-	
-	if ( *colonPos == 0 ) {
-	
-		// The propName is unqualified, use the schemaURI and associated prefix.
-		
-		expandedXPath->push_back ( XPathStepInfo ( schemaURI, kXMP_SchemaNode ) );
-		expandedXPath->push_back ( XPathStepInfo ( uriPos->second, 0 ) );
-		(*expandedXPath)[kRootPropStep].step += propName;
-	
-	} else {
-
-		// The propName is qualified. Make sure the prefix is legit. Use the associated URI and qualified name.
-
-		size_t prefixLen = colonPos - propName + 1;	// ! Include the colon.
-		VerifySimpleXMLName ( colonPos+1, colonPos+strlen(colonPos) );
-
-		XMP_VarString prefix ( propName, prefixLen );
-		XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( prefix );
-		if ( prefixPos == sNamespacePrefixToURIMap->end() ) {
-			XMP_Throw ( "Unknown schema namespace prefix", kXMPErr_BadSchema );
-		}
-		if ( prefix != uriPos->second ) {
-			XMP_Throw ( "Schema namespace URI and prefix mismatch", kXMPErr_BadSchema );
-		}
-
-		expandedXPath->push_back ( XPathStepInfo ( schemaURI, kXMP_SchemaNode ) );
-		expandedXPath->push_back ( XPathStepInfo ( propName, 0 ) );
-	
-	}
-
-}	// VerifyXPathRoot
-
-// -------------------------------------------------------------------------------------------------
-// VerifyQualName
-// --------------
-
-static void
-VerifyQualName ( XMP_StringPtr qualName, XMP_StringPtr nameEnd )
-{
-	if ( qualName >= nameEnd ) XMP_Throw ( "Empty qualified name", kXMPErr_BadXPath );
-
-	XMP_StringPtr colonPos = qualName;
-	while ( (colonPos < nameEnd) && (*colonPos != ':') ) ++colonPos;
-	if ( (colonPos == qualName) || (colonPos >= nameEnd) ) XMP_Throw ( "Ill-formed qualified name", kXMPErr_BadXPath );
-
-	VerifySimpleXMLName ( qualName, colonPos );
-	VerifySimpleXMLName ( colonPos+1, nameEnd );
-
-	size_t prefixLen = colonPos - qualName + 1;	// ! Include the colon.
-	XMP_VarString prefix ( qualName, prefixLen );
-	XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( prefix );
-	if ( prefixPos == sNamespacePrefixToURIMap->end() ) {
-		XMP_Throw ( "Unknown namespace prefix for qualified name", kXMPErr_BadXPath );
-	}
-
-}	// VerifyQualName
-
-// -------------------------------------------------------------------------------------------------
-// FindIndexedItem
-// ---------------
-//
-//	[index]	An element of an array.
-//
-// Support the implicit creation of a new last item.
-
-static XMP_Index
-FindIndexedItem ( XMP_Node * arrayNode, const XMP_VarString & indexStep, bool createNodes )
-{
-	XMP_Index index = 0;
-	size_t    chLim = indexStep.size() - 1;
-
-	XMP_Assert ( (chLim >= 2) && (indexStep[0] == '[') && (indexStep[chLim] == ']') );
-	
-	for ( size_t chNum = 1; chNum != chLim; ++chNum ) {
-		XMP_Assert ( ('0' <= indexStep[chNum]) && (indexStep[chNum] <= '9') );
-		index = (index * 10) + (indexStep[chNum] - '0');
-		if ( index < 0 ) {
-			XMP_Throw ( "Array index overflow", kXMPErr_BadXPath );	// ! Overflow, not truly negative.
-		}
-	}
-
-	--index;	// Change to a C-style, zero based index.
-	if ( index < 0 ) XMP_Throw ( "Array index must be larger than zero", kXMPErr_BadXPath );
-
-	if ( (index == (XMP_Index)arrayNode->children.size()) && createNodes ) {	// Append a new last+1 node.
-		XMP_Node * newItem = new XMP_Node ( arrayNode, kXMP_ArrayItemName, kXMP_NewImplicitNode );
-		arrayNode->children.push_back ( newItem );
-	}
-
-	// ! Don't throw here for a too large index. SetProperty will throw, GetProperty will not.
-	if ( index >= (XMP_Index)arrayNode->children.size() ) index = -1;
-	return index;
-	
-}	// FindIndexedItem
-
-// -------------------------------------------------------------------------------------------------
-// SplitNameAndValue
-// -----------------
-//
-// Split the name and value parts for field and qualifier selectors:
-//
-//	[qualName="value"]	An element in an array of structs, chosen by a field value.
-//	[?qualName="value"]	An element in an array, chosen by a qualifier value.
-//
-// The value portion is a string quoted by ''' or '"'. The value may contain any character including
-// a doubled quoting character. The value may be empty.
-
-static void
-SplitNameAndValue ( const XMP_VarString & selStep, XMP_VarString * nameStr, XMP_VarString * valueStr )
-{
-	XMP_StringPtr partBegin = selStep.c_str();
-	XMP_StringPtr partEnd;
-	
-	const XMP_StringPtr valueEnd = partBegin + (selStep.size() - 2);
-	const char          quote    = *valueEnd;
-	
-	XMP_Assert ( (*partBegin == '[') && (*(valueEnd+1) == ']') );
-	XMP_Assert ( (selStep.size() >= 6) && ((quote == '"') || (quote == '\'')) );
-
-	// Extract the name part.
-	
-	++partBegin;	// Skip the opening '['.
-	if ( *partBegin == '?' ) ++partBegin;
-	for ( partEnd = partBegin+1; *partEnd != '='; ++partEnd ) {};
-	
-	nameStr->assign ( partBegin, (partEnd - partBegin) );
-	
-	// Extract the value part, reducing doubled quotes.
-	
-	XMP_Assert ( *(partEnd+1) == quote );
-	
-	partBegin = partEnd + 2;
-	valueStr->erase();
-	valueStr->reserve ( valueEnd - partBegin );	// Maximum length, don't optimize doubled quotes.
-	
-	for ( partEnd = partBegin; partEnd < valueEnd; ++partEnd ) {
-		if ( (*partEnd == quote) && (*(partEnd+1) == quote) ) {
-			++partEnd;
-			valueStr->append ( partBegin, (partEnd - partBegin) );
-			partBegin = partEnd+1;	// ! Loop will increment partEnd again.
-		}
-	}
-
-	valueStr->append ( partBegin, (partEnd - partBegin) );	// ! The loop does not add the last part.
-
-}	// SplitNameAndValue
-
-// -------------------------------------------------------------------------------------------------
-// LookupQualSelector
-// ------------------
-//
-//	[?qualName="value"]	An element in an array, chosen by a qualifier value.
-//
-// Note that we don't create implicit nodes for qualifier selectors, so no CreateNodes parameter.
-
-static XMP_Index
-LookupQualSelector ( XMP_Node * arrayNode, const XMP_VarString & qualName, XMP_VarString & qualValue )
-{
-	XMP_Index index;
-		
-	if ( qualName == "xml:lang" ) {
-	
-		// *** Should check that the value is legit RFC 1766/3066.
-		NormalizeLangValue ( &qualValue );
-		index = LookupLangItem ( arrayNode, qualValue ) ;
-	
-	} else {
-
-		XMP_Index itemLim;
-		for ( index = 0, itemLim = arrayNode->children.size(); index != itemLim; ++index ) {
-
-			const XMP_Node * currItem = arrayNode->children[index];
-			XMP_Assert ( currItem->parent == arrayNode );
-			
-			size_t q, qualLim;
-			for ( q = 0, qualLim = currItem->qualifiers.size(); q != qualLim; ++q ) {
-				const XMP_Node * currQual = currItem->qualifiers[q];
-				XMP_Assert ( currQual->parent == currItem );
-				if ( currQual->name != qualName ) continue;
-				if ( currQual->value == qualValue ) break;	// Exit qual loop.
-			}
-			if ( q != qualLim ) break;	// Exit child loop, found an item with a matching qualifier.
-
-		}
-		if ( index == itemLim ) index = -1;
-
-	}
-	
-	return index;
-	
-}	// LookupQualSelector
-
-// -------------------------------------------------------------------------------------------------
-// FollowXPathStep
-// ---------------
-//
-// After processing by ExpandXPath, a step can be of these forms:
-//	qualName			A top level property or struct field.
-//	[index]				An element of an array.
-//	[last()]			The last element of an array.
-//	[qualName="value"]	An element in an array of structs, chosen by a field value.
-//	[?qualName="value"]	An element in an array, chosen by a qualifier value.
-//	?qualName			A general qualifier.
-//
-// Find the appropriate child node, resolving aliases, and optionally creating nodes.
-
-static XMP_Node *
-FollowXPathStep	( XMP_Node *	   parentNode,
-				  const XMP_ExpandedXPath & fullPath,
-				  size_t		   stepNum,
-				  bool			   createNodes,
-				  XMP_NodePtrPos * ptrPos,
-				  bool			   aliasedArrayItem = false )
-{
-	XMP_Node * nextNode = 0;
-	const XPathStepInfo & nextStep = fullPath[stepNum];
-	XMP_Index      index    = 0;
-	XMP_OptionBits stepKind = nextStep.options & kXMP_StepKindMask;
-	
-	XMP_Assert ( (kXMP_StructFieldStep <= stepKind) && (stepKind <= kXMP_FieldSelectorStep) );
-
-	if ( stepKind == kXMP_StructFieldStep ) {
-
-		nextNode = FindChildNode ( parentNode, nextStep.step.c_str(), createNodes, ptrPos );
-
-	} else if ( stepKind == kXMP_QualifierStep ) {
-	
-		XMP_StringPtr qualStep = nextStep.step.c_str();
-		XMP_Assert ( *qualStep == '?' );
-		++qualStep;
-		nextNode = FindQualifierNode ( parentNode, qualStep, createNodes, ptrPos );
-
-	} else {
-	
-		// This is an array indexing step. First get the index, then get the node.
-
-		if ( ! (parentNode->options & kXMP_PropValueIsArray) ) {
-			XMP_Throw ( "Indexing applied to non-array", kXMPErr_BadXPath );
-		}
-		
-		if ( stepKind == kXMP_ArrayIndexStep ) {
-			index = FindIndexedItem ( parentNode, nextStep.step, createNodes );
-		} else if ( stepKind == kXMP_ArrayLastStep ) {
-			index = parentNode->children.size() - 1;
-		} else if ( stepKind == kXMP_FieldSelectorStep ) {
-			XMP_VarString fieldName, fieldValue;
-			SplitNameAndValue ( nextStep.step, &fieldName, &fieldValue );
-			index = LookupFieldSelector ( parentNode, fieldName.c_str(), fieldValue.c_str() );
-		} else if ( stepKind == kXMP_QualSelectorStep ) {
-			XMP_VarString qualName, qualValue;
-			SplitNameAndValue ( nextStep.step, &qualName, &qualValue );
-			index = LookupQualSelector ( parentNode, qualName, qualValue );
-		} else {
-			XMP_Throw ( "Unknown array indexing step in FollowXPathStep", kXMPErr_InternalFailure );
-		}
-		
-		if ( (0 <= index) && (index <= (XMP_Index)parentNode->children.size()) ) nextNode = parentNode->children[index];
-
-		if ( (index == -1) && createNodes && aliasedArrayItem && (stepKind == kXMP_QualSelectorStep) ) {
-		
-			// An ugly special case without an obvious better place to be. We have an alias to the
-			// x-default item of an alt-text array. A simple reference via SetProperty must create
-			// the x-default item if it does not yet exist.
-			
-			XMP_Assert ( parentNode->options & kXMP_PropArrayIsAltText );
-			XMP_Assert ( (stepNum == 2) && (nextStep.step == "[?xml:lang=\"x-default\"]") );
-
-			nextNode = new XMP_Node ( parentNode, kXMP_ArrayItemName,
-									  (kXMP_PropHasQualifiers | kXMP_PropHasLang | kXMP_NewImplicitNode) );
-
-			XMP_Node * langQual = new XMP_Node ( nextNode, "xml:lang", "x-default", kXMP_PropIsQualifier );
-			nextNode->qualifiers.push_back ( langQual );
-
-			if ( parentNode->children.empty() ) {
-				parentNode->children.push_back ( nextNode );
-			} else {
-				parentNode->children.insert ( parentNode->children.begin(), nextNode );
-			}
-
-			index = 0;	// ! C-style index! The x-default item is always first.
-
-		}
-		
-		if ( (nextNode != 0) && (ptrPos != 0) ) *ptrPos = parentNode->children.begin() + index;
-	
-	}
-
-	if ( (nextNode != 0) && (nextNode->options & kXMP_NewImplicitNode) ) {
-		nextNode->options |= (nextStep.options & kXMP_PropArrayFormMask);
-	}
-	
-	XMP_Assert ( (ptrPos == 0) || (nextNode == 0) || (nextNode == **ptrPos) );
-	XMP_Assert ( (nextNode != 0) || (! createNodes) );
-	return nextNode;
-	
-}	// FollowXPathStep
-
-// -------------------------------------------------------------------------------------------------
-// CheckImplicitStruct
-// -------------------
-
-static inline void
-CheckImplicitStruct	( XMP_Node * node,
-					  const XMP_ExpandedXPath &	expandedXPath,
-					  size_t	 stepNum,
-					  size_t	 stepLim )
-{
-
-	if ( (stepNum < stepLim) &&
-		 ((node->options & kXMP_PropCompositeMask) == 0) &&
-		 (GetStepKind ( expandedXPath[stepNum].options ) == kXMP_StructFieldStep) ) {
-
-		node->options |= kXMP_PropValueIsStruct;
-
-	}
-
-}	// CheckImplicitStruct
-
-// -------------------------------------------------------------------------------------------------
-// DeleteSubtree
-// -------------
-
-// *** Might be useful elsewhere?
-
-static void
-DeleteSubtree ( XMP_NodePtrPos rootNodePos )
-{
-	XMP_Node * rootNode   = *rootNodePos;
-	XMP_Node * rootParent = rootNode->parent;
-
-	if ( ! (rootNode->options & kXMP_PropIsQualifier) ) {
-
-		rootParent->children.erase ( rootNodePos );
-
-	} else {
-
-		rootParent->qualifiers.erase ( rootNodePos );
-
-		XMP_Assert ( rootParent->options & kXMP_PropHasQualifiers);
-		if ( rootParent->qualifiers.empty() ) rootParent->options ^= kXMP_PropHasQualifiers;
-
-		if ( rootNode->name == "xml:lang" ) {
-			XMP_Assert ( rootParent->options & kXMP_PropHasLang);
-			rootParent->options ^= kXMP_PropHasLang;
-		} else if ( rootNode->name == "rdf:type" ) {
-			XMP_Assert ( rootParent->options & kXMP_PropHasType);
-			rootParent->options ^= kXMP_PropHasType;
-		}
-
-	}
-
-	delete rootNode;
-
-}	// DeleteSubtree
-
-// =================================================================================================
-// =================================================================================================
-
-// =================================================================================================
-// VerifySetOptions
-// ================
-//
-// Normalize and verify the option flags for SetProperty and similar functions. The allowed options
-// here are just those that apply to the property, that would be kept in the XMP_Node. Others that
-// affect the selection of the node or other processing must be removed by now. These are:
-//	kXMP_InsertBeforeItem
-//	kXMP_InsertAfterItem
-//	kXMP_KeepQualifiers
-//	kXMPUtil_AllowCommas
-
-enum {
-	kXMP_AllSetOptionsMask	= (kXMP_PropValueIsURI       |
-							   kXMP_PropValueIsStruct    |
-							   kXMP_PropValueIsArray     |
-							   kXMP_PropArrayIsOrdered   |
-							   kXMP_PropArrayIsAlternate |
-							   kXMP_PropArrayIsAltText   |
-							   kXMP_DeleteExisting)
-};
-
-XMP_OptionBits
-VerifySetOptions ( XMP_OptionBits options, XMP_StringPtr propValue )
-{
-
-	if ( options & kXMP_PropArrayIsAltText )   options |= kXMP_PropArrayIsAlternate;
-	if ( options & kXMP_PropArrayIsAlternate ) options |= kXMP_PropArrayIsOrdered;
-	if ( options & kXMP_PropArrayIsOrdered )   options |= kXMP_PropValueIsArray;
-	
-	if ( options & ~kXMP_AllSetOptionsMask ) {
-		XMP_Throw ( "Unrecognized option flags", kXMPErr_BadOptions );
-	}
-	
-	if ( (options & kXMP_PropValueIsStruct) && (options & kXMP_PropValueIsArray) ) {
-		XMP_Throw ( "IsStruct and IsArray options are mutually exclusive", kXMPErr_BadOptions );
-	}
-	
-	if ( (options & kXMP_PropValueOptionsMask) && (options & kXMP_PropCompositeMask) ) {
-		XMP_Throw ( "Structs and arrays can't have \"value\" options", kXMPErr_BadOptions );
-	}
-	
-	if ( (propValue != 0) && (options & kXMP_PropCompositeMask) ) {
-		XMP_Throw ( "Structs and arrays can't have string values", kXMPErr_BadOptions );
-	}
-
-	return options;
-
-}	// VerifySetOptions
-
-// =================================================================================================
-// ComposeXPath
-// ============
-//
-// Compose the canonical string form of an expanded XPath expression.
-
-extern void
-ComposeXPath ( const XMP_ExpandedXPath & expandedXPath,
-			   XMP_VarString * stringXPath )
-{
-	*stringXPath = expandedXPath[kRootPropStep].step;
-
-	for ( size_t index = kRootPropStep+1; index < expandedXPath.size(); ++index ) {
-		const XPathStepInfo & currStep = expandedXPath[index];
-
-		switch ( currStep.options & kXMP_StepKindMask ) {
-
-			case kXMP_StructFieldStep :
-			case kXMP_QualifierStep :
-				*stringXPath += '/';
-				*stringXPath += currStep.step;
-				break;
-
-			case kXMP_ArrayIndexStep :
-			case kXMP_ArrayLastStep :
-			case kXMP_QualSelectorStep :
-			case kXMP_FieldSelectorStep :
-				*stringXPath += currStep.step;
-				break;
-
-			default:
-				XMP_Throw ( "Unexpected", kXMPErr_InternalFailure );
-
-		}
-
-	}
-
-}	// ComposeXPath
-
-// =================================================================================================
-// ExpandXPath
-// ===========
-//
-// Split an XPath expression apart at the conceptual steps, adding the root namespace prefix to the
-// first property component. The schema URI is put in the first (0th) slot in the expanded XPath.
-// Check if the top level component is an alias, but don't resolve it.
-//
-// In the most verbose case steps are separated by '/', and each step can be of these forms:
-//
-//	qualName				A top level property or struct field.
-//	*[index]				An element of an array.
-//	*[last()]				The last element of an array.
-//	*[fieldName="value"]	An element in an array of structs, chosen by a field value.
-//	*[@xml:lang="value"]	An element in an alt-text array, chosen by the xml:lang qualifier.
-//	*[?qualName="value"]	An element in an array, chosen by a qualifier value.
-//	@xml:lang				An xml:lang qualifier.
-//	?qualName				A general qualifier.
-//
-// The logic is complicated though by shorthand for arrays, the separating '/' and leading '*'
-// are optional. These are all equivalent:  array/*[2]  array/[2]  array*[2]  array[2]
-// All of these are broken into the 2 steps "array" and "[2]".
-//
-// The value portion in the array selector forms is a string quoted by ''' or '"'. The value
-// may contain any character including a doubled quoting character. The value may be empty.
-//
-// The syntax isn't checked, but an XML name begins with a letter or '_', and contains letters,
-// digits, '.', '-', '_', and a bunch of special non-ASCII Unicode characters. An XML qualified
-// name is a pair of names separated by a colon.
-
-void
-ExpandXPath	( XMP_StringPtr			schemaNS,
-			  XMP_StringPtr			propPath,
-			  XMP_ExpandedXPath *	expandedXPath )
-{
-	XMP_Assert ( (schemaNS != 0) && (propPath != 0) && (*propPath != 0) && (expandedXPath != 0) );
-	
-	XMP_StringPtr	stepBegin, stepEnd;
-	XMP_StringPtr	qualName, nameEnd;
-	XMP_VarString	currStep;
-		
-	qualName = nameEnd = NULL;
-	size_t resCount = 2;	// Guess at the number of steps. At least 2, plus 1 for each '/' or '['.
-	for ( stepEnd = propPath; *stepEnd != 0; ++stepEnd ) {
-		if ( (*stepEnd == '/') || (*stepEnd == '[') ) ++resCount;
-	}
-	
-	expandedXPath->clear();
-	expandedXPath->reserve ( resCount );
-	
-	// -------------------------------------------------------------------------------------------
-	// Pull out the first component and do some special processing on it: add the schema namespace
-	// prefix and see if it is an alias. The start must be a qualName.
-	
-	stepBegin = propPath;
-	stepEnd = stepBegin;
-	while ( (*stepEnd != 0) && (*stepEnd != '/') && (*stepEnd != '[') && (*stepEnd != '*') ) ++stepEnd;
-	if ( stepEnd == stepBegin ) XMP_Throw ( "Empty initial XPath step", kXMPErr_BadXPath );
-	currStep.assign ( stepBegin, (stepEnd - stepBegin) );
-	
-	VerifyXPathRoot ( schemaNS, currStep.c_str(), expandedXPath );
-
-	XMP_OptionBits stepFlags = kXMP_StructFieldStep;	
-	if ( sRegisteredAliasMap->find ( (*expandedXPath)[kRootPropStep].step ) != sRegisteredAliasMap->end() ) {
-		stepFlags |= kXMP_StepIsAlias;
-	}
-	(*expandedXPath)[kRootPropStep].options |= stepFlags;
-		
-	// -----------------------------------------------------
-	// Now continue to process the rest of the XPath string.
-
-	while ( *stepEnd != 0 ) {
-
-		stepBegin = stepEnd;
-		if ( *stepBegin == '/' ) ++stepBegin;
-		if ( *stepBegin == '*' ) {
-			++stepBegin;
-			if ( *stepBegin != '[' ) XMP_Throw ( "Missing '[' after '*'", kXMPErr_BadXPath );
-		}
-		stepEnd = stepBegin;
-
-		if ( *stepBegin != '[' ) {
-		
-			// A struct field or qualifier.
-			qualName = stepBegin;
-			while ( (*stepEnd != 0) && (*stepEnd != '/') && (*stepEnd != '[') && (*stepEnd != '*') ) ++stepEnd;
-			nameEnd = stepEnd;
-			stepFlags = kXMP_StructFieldStep;	// ! Touch up later, also changing '@' to '?'.
-			
-		} else {
-		
-			// One of the array forms.
-		
-			++stepEnd;	// Look at the character after the leading '['.
-			
-			if ( ('0' <= *stepEnd) && (*stepEnd <= '9') ) {
-
-				// A numeric (decimal integer) array index.
-				while ( (*stepEnd != 0) && ('0' <= *stepEnd) && (*stepEnd <= '9') ) ++stepEnd;
-				if ( *stepEnd != ']' ) XMP_Throw ( "Missing ']' for integer array index", kXMPErr_BadXPath );
-				stepFlags = kXMP_ArrayIndexStep;
-
-			} else {
-
-				// Could be "[last()]" or one of the selector forms. Find the ']' or '='.
-				
-				while ( (*stepEnd != 0) && (*stepEnd != ']') && (*stepEnd != '=') ) ++stepEnd;
-				if ( *stepEnd == 0 ) XMP_Throw ( "Missing ']' or '=' for array index", kXMPErr_BadXPath );
-
-				if ( *stepEnd == ']' ) {
-
-					if ( strncmp ( "[last()", stepBegin, (stepEnd - stepBegin) ) != 0 ) {
-						XMP_Throw ( "Invalid non-numeric array index", kXMPErr_BadXPath );
-					}
-					stepFlags = kXMP_ArrayLastStep;
-
-				} else {
-
-					qualName = stepBegin+1;
-					nameEnd = stepEnd;
-					++stepEnd;	// Absorb the '=', remember the quote.
-					const char quote = *stepEnd;
-					if ( (quote != '\'') && (quote != '"') ) {
-						XMP_Throw ( "Invalid quote in array selector", kXMPErr_BadXPath );
-					}
-
-					++stepEnd;	// Absorb the leading quote.
-					while ( *stepEnd != 0 ) {
-						if ( *stepEnd == quote ) {
-							if ( *(stepEnd+1) != quote ) break;
-							++stepEnd;
-						}
-						++stepEnd;
-					}
-					if ( *stepEnd == 0 ) {
-						XMP_Throw ( "No terminating quote for array selector", kXMPErr_BadXPath );
-					}
-					++stepEnd;	// Absorb the trailing quote.
-					
-					stepFlags = kXMP_FieldSelectorStep;	// ! Touch up later, also changing '@' to '?'.
-
-				}
-
-			}
-
-			if ( *stepEnd != ']' ) XMP_Throw ( "Missing ']' for array index", kXMPErr_BadXPath );
-			++stepEnd;
-			
-		}
-
-		if ( stepEnd == stepBegin ) XMP_Throw ( "Empty XPath step", kXMPErr_BadXPath );
-		currStep.assign ( stepBegin, (stepEnd - stepBegin) );
-
-		if ( GetStepKind ( stepFlags ) == kXMP_StructFieldStep ) {
-
-			if ( currStep[0] == '@' ) {
-				currStep[0] = '?';
-				if ( currStep != "?xml:lang" ) XMP_Throw ( "Only xml:lang allowed with '@'", kXMPErr_BadXPath );
-			}
-			if ( currStep[0] == '?' ) {
-				++qualName;
-				stepFlags = kXMP_QualifierStep;
-			}
-			VerifyQualName ( qualName, nameEnd );
-
-		} else if ( GetStepKind ( stepFlags ) == kXMP_FieldSelectorStep ) {
-
-			if ( currStep[1] == '@' ) {
-				currStep[1] = '?';
-				if ( strncmp ( currStep.c_str(), "[?xml:lang=", 11 ) != 0 ) {
-					XMP_Throw ( "Only xml:lang allowed with '@'", kXMPErr_BadXPath );
-				}
-			}
-			if ( currStep[1] == '?' ) {
-				++qualName;
-				stepFlags = kXMP_QualSelectorStep;
-			}
-			VerifyQualName ( qualName, nameEnd );
-
-		}
-
-		expandedXPath->push_back ( XPathStepInfo ( currStep, stepFlags ) );
-
-	}
-
-}	// ExpandXPath
-
-// =================================================================================================
-// FindSchemaNode
-// ==============
-//
-// Find or create a schema node. Returns a pointer to the node, and optionally an iterator for the
-// node's position in the top level vector of schema nodes. The iterator is unchanged if no schema
-// node (null) is returned.
-
-XMP_Node *
-FindSchemaNode	( XMP_Node *		xmpTree,
-				  XMP_StringPtr		nsURI,
-				  bool				createNodes,
-				  XMP_NodePtrPos *	ptrPos /* = 0 */ )
-{
-	XMP_Node * schemaNode = 0;
-	
-	XMP_Assert ( xmpTree->parent == 0 );
-	
-	for ( size_t schemaNum = 0, schemaLim = xmpTree->children.size(); schemaNum != schemaLim; ++schemaNum ) {
-		XMP_Node * currSchema = xmpTree->children[schemaNum];
-		XMP_Assert ( currSchema->parent == xmpTree );
-		if ( currSchema->name == nsURI ) {
-			schemaNode = currSchema;
-			if ( ptrPos != 0 ) *ptrPos = xmpTree->children.begin() + schemaNum;
-			break;
-		}
-	}
-	
-	if ( (schemaNode == 0) && createNodes ) {
-
-		schemaNode = new XMP_Node ( xmpTree, nsURI, (kXMP_SchemaNode | kXMP_NewImplicitNode) );
-		XMP_StringPtr prefixPtr;
-		XMP_StringLen prefixLen;
-        bool found = XMPMeta::GetNamespacePrefix ( nsURI, &prefixPtr, &prefixLen );	// *** Use map directly?
-		XMP_Assert ( found );
-		UNUSED(found);
-
-		schemaNode->value.assign ( prefixPtr, prefixLen );
-		xmpTree->children.push_back ( schemaNode );
-		if ( ptrPos != 0 ) *ptrPos = xmpTree->children.end() - 1;
-
-		#if 0	// *** XMP_DebugBuild
-			schemaNode->_valuePtr = schemaNode->value.c_str();
-		#endif
-
-	}
-	
-	XMP_Assert ( (ptrPos == 0) || (schemaNode == 0) || (schemaNode == **ptrPos) );
-	XMP_Assert ( (schemaNode != 0) || (! createNodes) );
-	return schemaNode;
-	
-}	// FindSchemaNode
-
-// =================================================================================================
-// FindChildNode
-// =============
-//
-// Find or create a child node under a given parent node. Returns a pointer to the child node, and
-// optionally an iterator for the node's position in the parent's vector of children. The iterator
-// is unchanged if no child node (null) is returned.
-
-XMP_Node *
-FindChildNode	( XMP_Node *		parent,
-				  XMP_StringPtr		childName,
-				  bool				createNodes,
-				  XMP_NodePtrPos *	ptrPos /* = 0 */ )
-{
-	XMP_Node * childNode = 0;
-
-	if ( ! (parent->options & (kXMP_SchemaNode | kXMP_PropValueIsStruct)) ) {
-		if ( ! (parent->options & kXMP_NewImplicitNode) ) {
-			XMP_Throw ( "Named children only allowed for schemas and structs", kXMPErr_BadXPath );
-		}
-		if ( parent->options & kXMP_PropValueIsArray ) {
-			XMP_Throw ( "Named children not allowed for arrays", kXMPErr_BadXPath );
-		}
-		if ( ! createNodes ) {	// *** Should be assert? If !createNodes, why is the parent a new implicit node?
-			XMP_Throw ( "Parent is new implicit node, but createNodes is false", kXMPErr_InternalFailure );
-		}
-		parent->options |= kXMP_PropValueIsStruct;
-	}
-	
-	for ( size_t childNum = 0, childLim = parent->children.size(); childNum != childLim; ++childNum ) {
-		XMP_Node * currChild = parent->children[childNum];
-		XMP_Assert ( currChild->parent == parent );
-		if ( currChild->name == childName ) {
-			childNode = currChild;
-			if ( ptrPos != 0 ) *ptrPos = parent->children.begin() + childNum;
-			break;
-		}
-	}
-	
-	if ( (childNode == 0) && createNodes ) {
-		childNode = new XMP_Node ( parent, childName, kXMP_NewImplicitNode );
-		parent->children.push_back ( childNode );
-		if ( ptrPos != 0 ) *ptrPos = parent->children.end() - 1;
-	}
-	
-	XMP_Assert ( (ptrPos == 0) || (childNode == 0) || (childNode == **ptrPos) );
-	XMP_Assert ( (childNode != 0) || (! createNodes) );
-	return childNode;
-	
-}	// FindChildNode
-
-// =================================================================================================
-// FindQualifierNode
-// =================
-//
-// Find or create a qualifier node under a given parent node. Returns a pointer to the qualifier node,
-// and optionally an iterator for the node's position in the parent's vector of qualifiers. The iterator
-// is unchanged if no qualifier node (null) is returned.
-//
-// ! On entry, the qualName parameter must not have the leading '?' from the XPath step.
-
-XMP_Node *
-FindQualifierNode	( XMP_Node *		parent,
-					  XMP_StringPtr		qualName,
-					  bool				createNodes,
-					  XMP_NodePtrPos *	ptrPos /* = 0 */ )	// *** Require ptrPos internally & remove checks?
-{
-	XMP_Node * qualNode = 0;
-	
-	XMP_Assert ( *qualName != '?' );
-	
-	for ( size_t qualNum = 0, qualLim = parent->qualifiers.size(); qualNum != qualLim; ++qualNum ) {
-		XMP_Node * currQual = parent->qualifiers[qualNum];
-		XMP_Assert ( currQual->parent == parent );
-		if ( currQual->name == qualName ) {
-			qualNode = currQual;
-			if ( ptrPos != 0 ) *ptrPos = parent->qualifiers.begin() + qualNum;
-			break;
-		}
-	}
-	
-	if ( (qualNode == 0) && createNodes ) {
-
-		qualNode = new XMP_Node ( parent, qualName, (kXMP_PropIsQualifier | kXMP_NewImplicitNode) );
-		parent->options |= kXMP_PropHasQualifiers;
-
-		const bool isLang 	 = XMP_LitMatch ( qualName, "xml:lang" );
-		const bool isType 	 = XMP_LitMatch ( qualName, "rdf:type" );
-		const bool isSpecial = isLang | isType;
-
-		if ( isLang ) {
-			parent->options |= kXMP_PropHasLang;
-		} else if ( isType ) {
-			parent->options |= kXMP_PropHasType;
-		}
-		
-		if ( parent->qualifiers.empty() || (! isSpecial) ) {
-			parent->qualifiers.push_back ( qualNode );
-			if ( ptrPos != 0 ) *ptrPos = parent->qualifiers.end() - 1;
-		} else {
-			XMP_NodePtrPos insertPos = parent->qualifiers.begin();	// ! Lang goes first, type after.
-			if ( isType && (parent->options & kXMP_PropHasLang) ) ++insertPos;	// *** Does insert at end() work?
-			insertPos = parent->qualifiers.insert ( insertPos, qualNode );
-			if ( ptrPos != 0 ) *ptrPos = insertPos;
-		}
-
-	}
-	
-	XMP_Assert ( (ptrPos == 0) || (qualNode == 0) || (qualNode == **ptrPos) );
-	XMP_Assert ( (qualNode != 0) || (! createNodes) );
-	return qualNode;
-	
-}	// FindQualifierNode
-
-// =================================================================================================
-// LookupFieldSelector
-// ===================
-//
-//	[fieldName="value"]	An element in an array of structs, chosen by a field value.
-//
-// Note that we don't create implicit nodes for field selectors, so no CreateNodes parameter.
-
-XMP_Index
-LookupFieldSelector ( const XMP_Node * arrayNode, XMP_StringPtr fieldName, XMP_StringPtr fieldValue )
-{
-	XMP_Index index, itemLim;
-	
-	for ( index = 0, itemLim = arrayNode->children.size(); index != itemLim; ++index ) {
-
-		const XMP_Node * currItem = arrayNode->children[index];
-		XMP_Assert ( currItem->parent == arrayNode );
-
-		if ( ! (currItem->options & kXMP_PropValueIsStruct) ) {
-			XMP_Throw ( "Field selector must be used on array of struct", kXMPErr_BadXPath );
-		}
-
-		size_t f, fieldLim;
-		for ( f = 0, fieldLim = currItem->children.size(); f != fieldLim; ++f ) {
-			const XMP_Node * currField = currItem->children[f];
-			XMP_Assert ( currField->parent == currItem );
-			if ( currField->name != fieldName ) continue;
-			if ( currField->value == fieldValue ) break;	// Exit qual loop.
-		}
-		if ( f != fieldLim ) break;	// Exit child loop, found an item with a matching qualifier.
-
-	}
-	
-	if ( index == itemLim ) index = -1;
-	return index;
-	
-}	// LookupFieldSelector
-
-// =================================================================================================
-// LookupLangItem
-// ==============
-//
-// ! Assumes that the language value is already normalized.
-
-XMP_Index
-LookupLangItem ( const XMP_Node * arrayNode, XMP_VarString & lang )
-{
-	if ( ! (arrayNode->options & kXMP_PropValueIsArray) ) {	// *** Check for alt-text?
-		XMP_Throw ( "Language item must be used on array", kXMPErr_BadXPath );
-	}
-
-	XMP_Index index   = 0;
-	XMP_Index itemLim = arrayNode->children.size();
-	
-	for ( ; index != itemLim; ++index ) {
-		const XMP_Node * currItem = arrayNode->children[index];
-		XMP_Assert ( currItem->parent == arrayNode );
-		if ( currItem->qualifiers.empty() || (currItem->qualifiers[0]->name != "xml:lang") ) continue;
-		if ( currItem->qualifiers[0]->value == lang ) break;
-	}
-	
-	if ( index == itemLim ) index = -1;
-	return index;
-	
-}	// LookupLangItem
-
-// =================================================================================================
-// FindNode
-// ========
-//
-// Follow an expanded path expression to find or create a node. Returns a pointer to the node, and
-// optionally an iterator for the node's position in the parent's vector of children or qualifiers.
-// The iterator is unchanged if no child node (null) is returned.
-
-XMP_Node *
-FindNode ( XMP_Node *		xmpTree,
-		   const XMP_ExpandedXPath & expandedXPath,
-		   bool				createNodes,
-		   XMP_OptionBits	leafOptions /* = 0 */,
-	 	   XMP_NodePtrPos * ptrPos /* = 0 */ )
-{
-	XMP_Node *     currNode = 0;
-	XMP_NodePtrPos currPos;
-	XMP_NodePtrPos newSubPos;	// Root of implicitly created subtree. Valid only if leaf is new.
-	bool           leafIsNew = false;
-	
-	XMP_Assert ( (leafOptions == 0) || createNodes );
-
-	if ( expandedXPath.empty() ) XMP_Throw ( "Empty XPath", kXMPErr_BadXPath );
-	
-	size_t stepNum = 1;	// By default start calling FollowXPathStep for the top level property step.
-	size_t stepLim = expandedXPath.size();
-	
-	// The start of processing deals with the schema node and top level alias. If the top level step
-	// is not an alias, lookup the expanded path's schema URI. Otherwise, lookup the expanded path
-	// for the actual. While tempting, don't substitute the actual's path into the local one, don't
-	// risk messing with the caller's use of that. Also don't call FindNode recursively, we need to
-	// keep track of the root of the implicitly created subtree as we move down the path.
-	
-	if ( ! (expandedXPath[kRootPropStep].options & kXMP_StepIsAlias) ) {
-		
-		currNode = FindSchemaNode ( xmpTree, expandedXPath[kSchemaStep].step.c_str(), createNodes, &currPos );
-		if ( currNode == 0 ) return 0;
-
-		if ( currNode->options & kXMP_NewImplicitNode ) {
-			currNode->options ^= kXMP_NewImplicitNode;	// Clear the implicit node bit.
-			if ( ! leafIsNew ) newSubPos = currPos;	// Save the top most implicit node.
-			leafIsNew = true;	// If any parent is new, the leaf will be new also.
-		}
-
-	} else {
-
-		stepNum = 2;	// ! Continue processing the original path at the second level step.
-
-		XMP_AliasMapPos aliasPos = sRegisteredAliasMap->find ( expandedXPath[kRootPropStep].step );
-		XMP_Assert ( aliasPos != sRegisteredAliasMap->end() );
-		
-		currNode = FindSchemaNode ( xmpTree, aliasPos->second[kSchemaStep].step.c_str(), createNodes, &currPos );
-		if ( currNode == 0 ) goto EXIT;
-		if ( currNode->options & kXMP_NewImplicitNode ) {
-			currNode->options ^= kXMP_NewImplicitNode;	// Clear the implicit node bit.
-			if ( ! leafIsNew ) newSubPos = currPos;	// Save the top most implicit node.
-			leafIsNew = true;	// If any parent is new, the leaf will be new also.
-		}
-
-		currNode = FollowXPathStep ( currNode, aliasPos->second, 1, createNodes, &currPos );
-		if ( currNode == 0 ) goto EXIT;
-		if ( currNode->options & kXMP_NewImplicitNode ) {
-			currNode->options ^= kXMP_NewImplicitNode;	// Clear the implicit node bit.
-			CheckImplicitStruct ( currNode, expandedXPath, 2, stepLim );
-			if ( ! leafIsNew ) newSubPos = currPos;	// Save the top most implicit node.
-			leafIsNew = true;	// If any parent is new, the leaf will be new also.
-		}
-		
-		XMP_OptionBits arrayForm = aliasPos->second[kRootPropStep].options & kXMP_PropArrayFormMask;
-		XMP_Assert ( (arrayForm == 0) || (arrayForm & kXMP_PropValueIsArray) );
-		XMP_Assert ( (arrayForm == 0) ? (aliasPos->second.size() == 2) : (aliasPos->second.size() == 3) );
-		
-		if ( arrayForm != 0 ) { 
-			currNode = FollowXPathStep ( currNode, aliasPos->second, 2, createNodes, &currPos, true );
-			if ( currNode == 0 ) goto EXIT;
-			if ( currNode->options & kXMP_NewImplicitNode ) {
-				currNode->options ^= kXMP_NewImplicitNode;	// Clear the implicit node bit.
-				CheckImplicitStruct ( currNode, expandedXPath, 2, stepLim );
-				if ( ! leafIsNew ) newSubPos = currPos;	// Save the top most implicit node.
-				leafIsNew = true;	// If any parent is new, the leaf will be new also.
-			}
-		}
-		
-	}
-	
-	// Now follow the remaining steps of the original XPath.
-	
-	// *** ??? Change all the num/lim loops back to num<lim? Probably safer.
-	
-	try {
-		for ( ; stepNum < stepLim; ++stepNum ) {
-			currNode = FollowXPathStep ( currNode, expandedXPath, stepNum, createNodes, &currPos );
-			if ( currNode == 0 ) goto EXIT;
-			if ( currNode->options & kXMP_NewImplicitNode ) {
-				currNode->options ^= kXMP_NewImplicitNode;	// Clear the implicit node bit.
-				CheckImplicitStruct ( currNode, expandedXPath, stepNum+1, stepLim );
-				if ( ! leafIsNew ) newSubPos = currPos;	// Save the top most implicit node.
-				leafIsNew = true;	// If any parent is new, the leaf will be new also.
-			}
-		}
-	} catch ( ... ) {
-		if ( leafIsNew ) DeleteSubtree ( newSubPos );
-		throw;
-	}
-	
-	// Done. Delete the implicitly created subtree if the eventual node was not found.
-
-EXIT:
-
-	XMP_Assert ( (currNode == 0) || (currNode == *currPos) );
-	XMP_Assert ( (currNode != 0) || (! createNodes) );
-
-	if ( leafIsNew ) {
-		if ( currNode != 0 ) {
-			currNode->options |= leafOptions;
-		} else {
-			DeleteSubtree ( newSubPos );
-		}
-	}
-
-	if ( (currNode != 0) && (ptrPos != 0) ) *ptrPos = currPos;
-	return currNode;
-	
-}	// FindNode
-
-// =================================================================================================
-// CloneOffspring
-// ==============
-
-void
-CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent )
-{
-	size_t qualCount  = origParent->qualifiers.size();
-	size_t childCount = origParent->children.size();
-
-	if ( qualCount > 0 ) {
-
-		cloneParent->qualifiers.reserve ( qualCount );
-
-		for ( size_t qualNum = 0, qualLim = qualCount; qualNum != qualLim; ++qualNum ) {
-			const XMP_Node * origQual  = origParent->qualifiers[qualNum];
-			XMP_Node *       cloneQual = new XMP_Node ( cloneParent, origQual->name, origQual->value, origQual->options );
-			CloneOffspring ( origQual, cloneQual );
-			cloneParent->qualifiers.push_back ( cloneQual );
-		}
-
-	}
-	
-	if ( childCount > 0 ) {
-
-		cloneParent->children.reserve ( childCount );
-
-		for ( size_t childNum = 0, childLim = childCount; childNum != childLim; ++childNum ) {
-			const XMP_Node * origChild  = origParent->children[childNum];
-			XMP_Node *       cloneChild = new XMP_Node ( cloneParent, origChild->name, origChild->value, origChild->options );
-			CloneOffspring ( origChild, cloneChild );
-			cloneParent->children.push_back ( cloneChild );
-		}
-
-	}
-	
-}	// CloneOffspring
-
-// =================================================================================================
-// CloneSubtree
-// ============
-
-XMP_Node *
-CloneSubtree ( const XMP_Node * origRoot, XMP_Node * cloneParent )
-{
-	#if XMP_DebugBuild
-		if ( cloneParent->parent == 0 ) {
-			XMP_Assert ( origRoot->options & kXMP_SchemaNode );
-			XMP_Assert ( FindConstSchema ( cloneParent, origRoot->name.c_str() ) == 0 );
-		} else {
-			XMP_Assert ( ! (origRoot->options & kXMP_SchemaNode) );
-			if ( cloneParent->options & kXMP_PropValueIsStruct ) {	// Might be an array.
-				XMP_Assert ( FindConstChild ( cloneParent, origRoot->name.c_str() ) == 0 );
-			}
-		}
-	#endif
-	
-	XMP_Node * cloneRoot = new XMP_Node ( cloneParent, origRoot->name, origRoot->value, origRoot->options );
-	CloneOffspring ( origRoot, cloneRoot ) ;
-	cloneParent->children.push_back ( cloneRoot );
-	
-	return cloneRoot;
-	
-}	// CloneSubtree
-
-// =================================================================================================
-// CompareSubtrees
-// ===============
-//
-// Compare 2 subtrees for semantic equality. The comparison includes value, qualifiers, and form.
-// Schemas, top level properties, struct fields, and qualifiers are allowed to have differing order,
-// the appropriate right node is found from the left node's name. Alt-text arrays are allowed to be
-// in differing language order, other arrays are compared in order.
-
-// *** Might someday consider sorting unordered arrays.
-// *** Should expose this through XMPUtils.
-
-bool
-CompareSubtrees ( const XMP_Node & leftNode, const XMP_Node & rightNode )
-{
-	// Don't compare the names here, we want to allow the outermost roots to have different names.
-	if ( (leftNode.value != rightNode.value) ||
-	     (leftNode.options != rightNode.options) ||
-	     (leftNode.children.size() != rightNode.children.size()) ||
-	     (leftNode.qualifiers.size() != rightNode.qualifiers.size()) ) return false;
-	
-	// Compare the qualifiers, allowing them to be out of order.
-	for ( size_t qualNum = 0, qualLim = leftNode.qualifiers.size(); qualNum != qualLim; ++qualNum ) {
-		const XMP_Node * leftQual  = leftNode.qualifiers[qualNum];
-		const XMP_Node * rightQual = FindConstQualifier ( &rightNode, leftQual->name.c_str() );
-		if ( (rightQual == 0) || (! CompareSubtrees ( *leftQual, *rightQual )) ) return false;
-	}
-	
-	if ( (leftNode.parent == 0) || (leftNode.options & (kXMP_SchemaNode | kXMP_PropValueIsStruct)) ) {
-
-		// The parent node is a tree root, a schema, or a struct.
-		for ( size_t childNum = 0, childLim = leftNode.children.size(); childNum != childLim; ++childNum ) {
-			const XMP_Node * leftChild  = leftNode.children[childNum];
-			const XMP_Node * rightChild = FindConstChild ( &rightNode, leftChild->name.c_str() );
-			if ( (rightChild == 0) || (! CompareSubtrees ( *leftChild, *rightChild )) ) return false;
-		}
-
-	} else if ( leftNode.options & kXMP_PropArrayIsAltText ) {
-
-		// The parent node is an alt-text array.
-		for ( size_t childNum = 0, childLim = leftNode.children.size(); childNum != childLim; ++childNum ) {
-			const XMP_Node * leftChild = leftNode.children[childNum];
-			XMP_Assert ( (! leftChild->qualifiers.empty()) && (leftChild->qualifiers[0]->name == "xml:lang") );
-			XMP_Index rightIndex = LookupLangItem ( &rightNode, leftChild->qualifiers[0]->value );
-			if ( rightIndex == -1 ) return false;
-			const XMP_Node * rightChild = rightNode.children[rightIndex];
-			if ( ! CompareSubtrees ( *leftChild, *rightChild ) ) return false;
-		}
-
-	} else {
-
-		// The parent must be simple or some other (not alt-text) kind of array.
-		XMP_Assert ( (! (leftNode.options & kXMP_PropCompositeMask)) || (leftNode.options & kXMP_PropValueIsArray) );
-		for ( size_t childNum = 0, childLim = leftNode.children.size(); childNum != childLim; ++childNum ) {
-			const XMP_Node * leftChild  = leftNode.children[childNum];
-			const XMP_Node * rightChild = rightNode.children[childNum];
-			if ( ! CompareSubtrees ( *leftChild, *rightChild ) ) return false;
-		}
-
-	}
-	
-	return true;
-	
-}	// CompareSubtrees
-
-// =================================================================================================
-// DeleteEmptySchema
-// =================
-
-void
-DeleteEmptySchema ( XMP_Node * schemaNode )
-{
-
-	if ( XMP_NodeIsSchema ( schemaNode->options ) && schemaNode->children.empty() ) {
-
-		XMP_Node * xmpTree = schemaNode->parent;
-
-		size_t schemaNum = 0;
-		size_t schemaLim = xmpTree->children.size();
-		while ( (schemaNum < schemaLim) && (xmpTree->children[schemaNum] != schemaNode) ) ++schemaNum;
-		XMP_Assert ( schemaNum < schemaLim );
-
-		XMP_NodePtrPos schemaPos = xmpTree->children.begin() + schemaNum;
-		XMP_Assert ( *schemaPos == schemaNode );
-
-		xmpTree->children.erase ( schemaPos );
-		delete schemaNode;
-
-	}
-
-}	// DeleteEmptySchema
-
-// =================================================================================================
-// NormalizeLangValue
-// ==================
-//
-// Normalize an xml:lang value so that comparisons are effectively case insensitive as required by
-// RFC 3066 (which superceeds RFC 1766). The normalization rules:
-//
-//	- The primary subtag is lower case, the suggested practice of ISO 639.
-//	- All 2 letter secondary subtags are upper case, the suggested practice of ISO 3166.
-//	- All other subtags are lower case.
-
-void
-NormalizeLangValue ( XMP_VarString * value )
-{
-	char * tagStart;
-	char * tagEnd;
-
-	// Find and process the primary subtag.
-	
-	tagStart = (char*) value->c_str();
-	for ( tagEnd = tagStart; (*tagEnd != 0) && (*tagEnd != '-'); ++tagEnd ) {
-		if ( ('A' <= *tagEnd) && (*tagEnd <= 'Z') ) *tagEnd += 0x20;
-	}
-	
-	// Find and process the secondary subtag.
-	
-	tagStart = tagEnd;
-	if ( *tagStart == '-' ) ++tagStart;
-	for ( tagEnd = tagStart; (*tagEnd != 0) && (*tagEnd != '-'); ++tagEnd ) {
-		if ( ('A' <= *tagEnd) && (*tagEnd <= 'Z') ) *tagEnd += 0x20;
-	}
-	if ( tagEnd == tagStart+2 ) {
-		if ( ('a' <= *tagStart) && (*tagStart <= 'z') ) *tagStart -= 0x20;
-		++tagStart;
-		if ( ('a' <= *tagStart) && (*tagStart <= 'z') ) *tagStart -= 0x20;
-	}
-	
-	// Find and process the remaining subtags.
-	
-	while ( true ) {
-		tagStart = tagEnd;
-		if ( *tagStart == '-' ) ++tagStart;
-		if ( *tagStart == 0 ) break;
-		for ( tagEnd = tagStart; (*tagEnd != 0) && (*tagEnd != '-'); ++tagEnd ) {
-			if ( ('A' <= *tagEnd) && (*tagEnd <= 'Z') ) *tagEnd += 0x20;
-		}
-	}
-	
-}	// NormalizeLangValue
-
-// =================================================================================================
-// NormalizeLangArray
-// ==================
-//
-// Make sure the x-default item is first. Touch up "single value" arrays that have a default plus
-// one real language. This case should have the same value for both items. Older Adobe apps were
-// hardwired to only use the 'x-default' item, so we copy that value to the other item.
-
-void
-NormalizeLangArray ( XMP_Node * array )
-{
-	XMP_Assert ( XMP_ArrayIsAltText(array->options) );
-	
-	size_t itemNum;
-	size_t itemLim = array->children.size();
-	bool   hasDefault = false;
-	
-	for ( itemNum = 0; itemNum < itemLim; ++itemNum ) {
-	
-		if ( array->children[itemNum]->qualifiers.empty() ||
-			 (array->children[itemNum]->qualifiers[0]->name != "xml:lang") ) {
-			XMP_Throw ( "AltText array items must have an xml:lang qualifier", kXMPErr_BadXMP );
-		}
-
-		if ( array->children[itemNum]->qualifiers[0]->value == "x-default" ) {
-			hasDefault = true;
-			break;
-		}
-
-	}
-
-	if ( hasDefault ) {
-
-		if ( itemNum != 0 ) {
-			XMP_Node * temp = array->children[0];
-			array->children[0] = array->children[itemNum];
-			array->children[itemNum] = temp;
-		}
-
-// 09-Oct-07, ahu: disabled to avoid unexpected behaviour
-//		if ( itemLim == 2 ) array->children[1]->value = array->children[0]->value;
-
-	}
-	
-}	// NormalizeLangArray
-
-// =================================================================================================
-// DetectAltText
-// =============
-//
-// See if an array is an alt-text array. If so, make sure the x-default item is first.
-
-void
-DetectAltText ( XMP_Node * xmpParent )
-{
-	XMP_Assert ( XMP_ArrayIsAlternate(xmpParent->options) );
-
-	size_t itemNum, itemLim;
-	
-	for ( itemNum = 0, itemLim = xmpParent->children.size(); itemNum < itemLim; ++itemNum ) {
-		XMP_OptionBits currOptions = xmpParent->children[itemNum]->options;
-		if ( (currOptions & kXMP_PropCompositeMask) || (! (currOptions & kXMP_PropHasLang)) ) break;
-	}
-	
-	if ( (itemLim != 0) && (itemNum == itemLim) ) {
-		xmpParent->options |= kXMP_PropArrayIsAltText;
-		NormalizeLangArray ( xmpParent );
-	}
-
-}	// DetectAltText
-
-// =================================================================================================
-// SortNamedNodes
-// ==============
-//
-// Sort the pointers in an XMP_NodeOffspring vector by name.
-
-static inline bool Compare ( const XMP_Node * left, const XMP_Node * right )
-{
-	return (left->name < right->name);
-}
-
-void
-SortNamedNodes ( XMP_NodeOffspring & nodeVector )
-{
-	sort ( nodeVector.begin(), nodeVector.end(), Compare );
-}	// SortNamedNodes
-
-// =================================================================================================
diff --git a/xmpsdk/src/XMPCore_Impl.hpp b/xmpsdk/src/XMPCore_Impl.hpp
deleted file mode 100644
index 7d57de6c..00000000
--- a/xmpsdk/src/XMPCore_Impl.hpp
+++ /dev/null
@@ -1,534 +0,0 @@
-#ifndef __XMPCore_Impl_hpp__
-#define __XMPCore_Impl_hpp__
-
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! Must be the first #include!
-#include "XMP_Const.h"
-#include "XMP_BuildInfo.h"
-
-#include "client-glue/WXMPMeta.hpp"
-
-#include <vector>
-#include <string>
-#include <map>
-
-#include <cassert>
-#include <cstring>
-
-#if XMP_WinBuild
-	#include <windows.h>
-#else
-	// Use pthread for both Mac and generic UNIX.
-	#include <pthread.h>
-#endif
-
-#if XMP_WinBuild
-#   ifdef _MSC_VER
-        #pragma warning ( disable : 4244 )	// possible loss of data (temporary for 64 bit builds)
-        #pragma warning ( disable : 4267 )	// possible loss of data (temporary for 64 bit builds)
-#   endif
-#endif
-
-// =================================================================================================
-// Primary internal types
-
-class XMP_Node;
-class XML_Node;
-class XPathStepInfo;
-
-typedef XMP_Node *	XMP_NodePtr;
-
-typedef std::vector<XMP_Node*>		XMP_NodeOffspring;
-typedef XMP_NodeOffspring::iterator	XMP_NodePtrPos;
-
-typedef std::string	XMP_VarString;
-typedef XMP_VarString::iterator			XMP_VarStringPos;
-typedef XMP_VarString::const_iterator	XMP_cVarStringPos;
-
-typedef std::pair < XMP_VarString, XMP_VarString >	XMP_StringPair;
-
-typedef std::map < XMP_VarString, XMP_VarString > XMP_StringMap;
-typedef XMP_StringMap::iterator			XMP_StringMapPos;
-typedef XMP_StringMap::const_iterator	XMP_cStringMapPos;
-
-typedef std::vector < XPathStepInfo >		XMP_ExpandedXPath;
-typedef XMP_ExpandedXPath::iterator			XMP_ExpandedXPathPos;
-typedef XMP_ExpandedXPath::const_iterator	XMP_cExpandedXPathPos;
-
-typedef std::map < XMP_VarString, XMP_ExpandedXPath > XMP_AliasMap;	// Alias name to actual path.
-typedef XMP_AliasMap::iterator			XMP_AliasMapPos;
-typedef XMP_AliasMap::const_iterator	XMP_cAliasMapPos;
-
-// =================================================================================================
-// General global variables and macros
-
-extern XMP_Int32 sXMP_InitCount;
-
-extern XMP_AliasMap *	sRegisteredAliasMap;
-
-extern XMP_StringMap *	sNamespaceURIToPrefixMap;
-extern XMP_StringMap *	sNamespacePrefixToURIMap;
-
-extern XMP_VarString *	sOutputNS;
-extern XMP_VarString *	sOutputStr;
-
-extern void *			voidVoidPtr;	// Used to backfill null output parameters.
-extern XMP_StringPtr	voidStringPtr;
-extern XMP_StringLen	voidStringLen;
-extern XMP_OptionBits	voidOptionBits;
-extern XMP_Bool			voidByte;
-extern bool				voidBool;
-extern XMP_Int32		voidInt32;
-extern XMP_Int64		voidInt64;
-extern double			voidDouble;
-extern XMP_DateTime		voidDateTime;
-extern WXMP_Result		void_wResult;
-
-#define kHexDigits "0123456789ABCDEF"
-
-#define XMP_LitMatch(s,l)		(std::strcmp((s),(l)) == 0)
-#define XMP_LitNMatch(s,l,n)	(std::strncmp((s),(l),(n)) == 0)
-	// *** Use the above macros!
-
-#define kTab ((char)0x09)
-#define kLF ((char)0x0A)
-#define kCR ((char)0x0D)
-
-#if XMP_WinBuild
-	#define snprintf _snprintf
-#endif
-
-#define WtoXMPMeta_Ref(xmpRef)	*((const XMPMeta *)(xmpRef))
-#define WtoXMPMeta_Ptr(xmpRef)	(((xmpRef) == 0) ? 0 : (XMPMeta *)(xmpRef))
-
-#define WtoXMPIterator_Ref(iterRef)	*((const XMPIterator *)(iterRef))
-#define WtoXMPIterator_Ptr(iterRef)	(((iterRef) == 0) ? 0 : (XMPIterator *)(iterRef))
-
-#define WtoXMPDocOps_Ref(docRef)	*((const XMPDocOps *)(docRef))
-#define WtoXMPDocOps_Ptr(docRef)	(((docRef) == 0) ? 0 : (XMPDocOps *)(docRef))
-
-#define IgnoreParam(p)	voidVoidPtr = (void*)&p
-
-// =================================================================================================
-// Version info
-
-#if XMP_DebugBuild
-	#define kXMPCore_DebugFlag 1
-#else
-	#define kXMPCore_DebugFlag 0
-#endif
-
-#define kXMPCore_VersionNumber	( (kXMPCore_DebugFlag << 31)    |	\
-                                  (XMP_API_VERSION_MAJOR << 24) |	\
-						          (XMP_API_VERSION_MINOR << 16) |	\
-						          (XMP_API_VERSION_MICRO << 8) )
-
-	#define kXMPCoreName "XMP Core"
-	#define kXMPCore_VersionMessage	kXMPCoreName " " XMP_API_VERSION_STRING
-// =================================================================================================
-// Support for asserts
-
-#define _MakeStr(p)			#p
-#define _NotifyMsg(n,c,f,l)	#n " failed: " #c " in " f " at line " _MakeStr(l)
-
-#if ! XMP_DebugBuild
-	#define XMP_Assert(c)	((void) 0)
-#else
-		#define XMP_Assert(c)	assert ( c )
-#endif
-
-	#define XMP_Enforce(c)																			\
-		if ( ! (c) ) {																				\
-			const char * assert_msg = _NotifyMsg ( XMP_Enforce, (c), __FILE__, __LINE__ );			\
-			XMP_Throw ( assert_msg , kXMPErr_EnforceFailure );										\
-		}
-// =================================================================================================
-// Support for exceptions and thread locking
-
-#ifndef TraceXMPCalls
-	#define TraceXMPCalls	0
-#endif
-
-#if ! TraceXMPCalls
-
-	#define AnnounceThrow(msg)		/* Do nothing. */
-	#define AnnounceCatch(msg)		/* Do nothing. */
-
-	#define AnnounceEntry(proc)		/* Do nothing. */
-	#define AnnounceNoLock(proc)	/* Do nothing. */
-	#define AnnounceExit()			/* Do nothing. */
-
-	#define ReportLock()			++sLockCount
-	#define ReportUnlock()			--sLockCount
-	#define ReportKeepLock()		/* Do nothing. */
-
-#else
-
-	extern FILE * xmpCoreOut;
-
-	#define AnnounceThrow(msg)	\
-		fprintf ( xmpCoreOut, "XMP_Throw: %s\n", msg ); fflush ( xmpOut )
-	#define AnnounceCatch(msg)	\
-		fprintf ( xmpCoreOut, "Catch in %s: %s\n", procName, msg ); fflush ( xmpOut )
-
-	#define AnnounceEntry(proc)			\
-		const char * procName = proc;	\
-		fprintf ( xmpCoreOut, "Entering %s\n", procName ); fflush ( xmpOut )
-	#define AnnounceNoLock(proc)		\
-		const char * procName = proc;	\
-		fprintf ( xmpCoreOut, "Entering %s (no lock)\n", procName ); fflush ( xmpOut )
-	#define AnnounceExit()	\
-		fprintf ( xmpCoreOut, "Exiting %s\n", procName ); fflush ( xmpOut )
-
-	#define ReportLock()	\
-		++sLockCount; fprintf ( xmpCoreOut, "  Auto lock, count = %d\n", sLockCount ); fflush ( xmpOut )
-	#define ReportUnlock()	\
-		--sLockCount; fprintf ( xmpCoreOut, "  Auto unlock, count = %d\n", sLockCount ); fflush ( xmpOut )
-	#define ReportKeepLock()	\
-		fprintf ( xmpCoreOut, "  Keeping lock, count = %d\n", sLockCount ); fflush ( xmpOut )
-
-#endif
-
-#define XMP_Throw(msg,id)	{ AnnounceThrow ( msg ); throw XMP_Error ( id, msg ); }
-
-// -------------------------------------------------------------------------------------------------
-
-#if XMP_WinBuild
-	typedef CRITICAL_SECTION XMP_Mutex;
-#else
-	// Use pthread for both Mac and generic UNIX.
-	typedef pthread_mutex_t XMP_Mutex;
-#endif
-
-extern XMP_Mutex sXMPCoreLock;
-extern int	sLockCount;	// Keep signed to catch unlock errors.
-extern XMP_VarString * sExceptionMessage;
-
-extern bool XMP_InitMutex ( XMP_Mutex * mutex );
-extern void XMP_TermMutex ( XMP_Mutex & mutex );
-
-extern void XMP_EnterCriticalRegion ( XMP_Mutex & mutex );
-extern void XMP_ExitCriticalRegion ( XMP_Mutex & mutex );
-
-class XMP_AutoMutex {
-public:
-	XMP_AutoMutex() : mutex(&sXMPCoreLock) { XMP_EnterCriticalRegion ( *mutex ); ReportLock(); };
-	~XMP_AutoMutex() { if ( mutex != 0 ) { ReportUnlock(); XMP_ExitCriticalRegion ( *mutex ); mutex = 0; } };
-	void KeepLock() { ReportKeepLock(); mutex = 0; };
-private:
-	XMP_Mutex * mutex;
-};
-
-// *** Switch to XMPEnterObjectWrapper & XMPEnterStaticWrapper, to allow for per-object locks.
-
-// ! Don't do the initialization check (sXMP_InitCount > 0) for the no-lock case. That macro is used
-// ! by WXMPMeta_Initialize_1.
-
-#define XMP_ENTER_WRAPPER_NO_LOCK(proc)						\
-	AnnounceNoLock ( proc );								\
-	XMP_Assert ( (0 <= sLockCount) && (sLockCount <= 1) );	\
-	try {													\
-		wResult->errMessage = 0;
-
-#define XMP_ENTER_WRAPPER(proc)								\
-	AnnounceEntry ( proc );									\
-	XMP_Assert ( sXMP_InitCount > 0 );	                    \
-	XMP_Assert ( (0 <= sLockCount) && (sLockCount <= 1) );	\
-	try {													\
-		XMP_AutoMutex mutex;								\
-		wResult->errMessage = 0;
-
-#define XMP_EXIT_WRAPPER	\
-	XMP_CATCH_EXCEPTIONS	\
-	AnnounceExit();
-
-#define XMP_EXIT_WRAPPER_KEEP_LOCK(keep)	\
-		if ( keep ) mutex.KeepLock();		\
-	XMP_CATCH_EXCEPTIONS					\
-	AnnounceExit();
-
-#define XMP_EXIT_WRAPPER_NO_THROW				\
-	} catch ( ... )	{							\
-		AnnounceCatch ( "no-throw catch-all" );	\
-		/* Do nothing. */						\
-	}											\
-	AnnounceExit();
-
-#define XMP_CATCH_EXCEPTIONS										\
-	} catch ( XMP_Error & xmpErr ) {								\
-		wResult->int32Result = xmpErr.GetID(); 						\
-		wResult->ptrResult   = (void*)"XMP";						\
-		wResult->errMessage  = xmpErr.GetErrMsg();					\
-		if ( wResult->errMessage == 0 ) wResult->errMessage = "";	\
-		AnnounceCatch ( wResult->errMessage );						\
-	} catch ( std::exception & stdErr ) {							\
-		wResult->int32Result = kXMPErr_StdException; 				\
-		wResult->errMessage  = stdErr.what(); 						\
-		if ( wResult->errMessage == 0 ) wResult->errMessage = "";	\
-		AnnounceCatch ( wResult->errMessage );						\
-	} catch ( ... ) {												\
-		wResult->int32Result = kXMPErr_UnknownException; 			\
-		wResult->errMessage  = "Caught unknown exception";			\
-		AnnounceCatch ( wResult->errMessage );						\
-	}
-
-#if XMP_DebugBuild
-	#define RELEASE_NO_THROW	/* empty */
-#else
-	#define RELEASE_NO_THROW	throw()
-#endif
-
-// =================================================================================================
-// ExpandXPath, FindNode, and related support
-
-// *** Normalize the use of "const xx &" for input params
-
-#define kXMP_ArrayItemName	"[]"
-
-#define kXMP_CreateNodes	true
-#define kXMP_ExistingOnly	false
-
-#define FindConstSchema(t,u)	FindSchemaNode ( const_cast<XMP_Node*>(t), u, kXMP_ExistingOnly, 0 )
-#define FindConstChild(p,c)		FindChildNode ( const_cast<XMP_Node*>(p), c, kXMP_ExistingOnly, 0 )
-#define FindConstQualifier(p,c)	FindQualifierNode ( const_cast<XMP_Node*>(p), c, kXMP_ExistingOnly, 0 )
-#define FindConstNode(t,p)		FindNode ( const_cast<XMP_Node*>(t), p, kXMP_ExistingOnly, 0 )
-
-extern XMP_OptionBits
-VerifySetOptions ( XMP_OptionBits options, XMP_StringPtr propValue );
-
-extern void
-ComposeXPath ( const XMP_ExpandedXPath & expandedXPath,
-			   XMP_VarString * stringXPath );
-
-extern void
-ExpandXPath	( XMP_StringPtr			schemaNS,
-			  XMP_StringPtr			propPath,
-			  XMP_ExpandedXPath *	expandedXPath );
-
-extern XMP_Node *
-FindSchemaNode ( XMP_Node *		  xmpTree,
-				 XMP_StringPtr	  nsURI,
-				 bool			  createNodes,
-				 XMP_NodePtrPos * ptrPos = 0 );
-
-extern XMP_Node *
-FindChildNode ( XMP_Node *		 parent,
-				XMP_StringPtr	 childName,
-				bool			 createNodes,
-				XMP_NodePtrPos * ptrPos = 0 );
-
-extern XMP_Node *
-FindQualifierNode ( XMP_Node *		 parent,
-					XMP_StringPtr	 qualName,
-					bool			 createNodes,
-					XMP_NodePtrPos * ptrPos = 0 );
-
-extern XMP_Node *
-FindNode ( XMP_Node *		xmpTree,
-		   const XMP_ExpandedXPath & expandedXPath,
-		   bool				createNodes,
-		   XMP_OptionBits	leafOptions = 0,
-		   XMP_NodePtrPos * ptrPos = 0 );
-
-extern XMP_Index
-LookupLangItem ( const XMP_Node * arrayNode, XMP_VarString & lang );	// ! Lang must be normalized!
-
-extern XMP_Index
-LookupFieldSelector ( const XMP_Node * arrayNode, XMP_StringPtr fieldName, XMP_StringPtr fieldValue );
-
-extern void
-CloneOffspring ( const XMP_Node * origParent, XMP_Node * cloneParent );
-
-extern XMP_Node *
-CloneSubtree ( const XMP_Node * origRoot, XMP_Node * cloneParent );
-
-extern bool
-CompareSubtrees ( const XMP_Node & leftNode, const XMP_Node & rightNode );
-
-extern void
-DeleteEmptySchema ( XMP_Node * schemaNode );
-
-extern void
-NormalizeLangValue ( XMP_VarString * value );
-
-extern void
-NormalizeLangArray ( XMP_Node * array );
-
-extern void
-DetectAltText ( XMP_Node * xmpParent );
-
-extern void
-SortNamedNodes ( XMP_NodeOffspring & nodeVector );
-
-static inline bool
-IsPathPrefix ( XMP_StringPtr fullPath, XMP_StringPtr prefix )
-{
-	bool isPrefix = false;
-	XMP_StringLen prefixLen = std::strlen(prefix);
-	if ( XMP_LitNMatch ( prefix, fullPath, prefixLen ) ) {
-		char separator = fullPath[prefixLen];
-		if ( (separator == 0) || (separator == '/') ||
-			 (separator == '[') || (separator == '*') ) isPrefix = true;
-	}
-	return isPrefix;
-}
-
-// -------------------------------------------------------------------------------------------------
-
-class XPathStepInfo {
-public:
-	XMP_VarString	step;
-	XMP_OptionBits	options;
-	XPathStepInfo ( XMP_StringPtr _step, XMP_OptionBits _options ) : step(_step), options(_options) {};
-	XPathStepInfo ( XMP_VarString _step, XMP_OptionBits _options ) : step(_step), options(_options) {};
-private:
-	XPathStepInfo() : options(0) {};	// ! Hide the default constructor.
-};
-
-enum { kSchemaStep = 0, kRootPropStep = 1, kAliasIndexStep = 2 };
-
-enum {	// Bits for XPathStepInfo options.	// *** Add mask check to init code.
-	kXMP_StepKindMask		= 0x0F,	// ! The step kinds are mutually exclusive numbers.
-	kXMP_StructFieldStep	= 0x01,	// Also for top level nodes (schema "fields").
-	kXMP_QualifierStep		= 0x02,	// ! Order is significant to separate struct/qual from array kinds!
-	kXMP_ArrayIndexStep		= 0x03,	// ! The kinds must not overlay array form bits!
-	kXMP_ArrayLastStep		= 0x04,
-	kXMP_QualSelectorStep	= 0x05,
-	kXMP_FieldSelectorStep	= 0x06,
-	kXMP_StepIsAlias        = 0x10
-};
-
-#define GetStepKind(f)	((f) & kXMP_StepKindMask)
-
-#define kXMP_NewImplicitNode	kXMP_InsertAfterItem
-
-// =================================================================================================
-// XMP_Node details
-
-#if 0	// Pattern for iterating over the children or qualifiers:
-	for ( size_t xxNum = 0, xxLim = _node_->_offspring_.size(); xxNum < xxLim; ++xxNum ) {
-		const XMP_Node * _curr_ = _node_->_offspring_[xxNum];
-	}
-#endif
-
-class XMP_Node {
-public:
-
-	XMP_OptionBits		options;
-	XMP_VarString		name, value;
-	XMP_Node *			parent;
-	XMP_NodeOffspring	children;
-	XMP_NodeOffspring	qualifiers;
-	#if XMP_DebugBuild
-		// *** XMP_StringPtr	_namePtr, _valuePtr;	// *** Not working, need operator=?
-	#endif
-
-	XMP_Node ( XMP_Node * _parent, XMP_StringPtr _name, XMP_OptionBits _options )
-		: options(_options), name(_name), parent(_parent)
-	{
-		#if XMP_DebugBuild
-			XMP_Assert ( (name.find ( ':' ) != XMP_VarString::npos) || (name == kXMP_ArrayItemName) ||
-			             (options & kXMP_SchemaNode) || (parent == 0) );
-			// *** _namePtr  = name.c_str();
-			// *** _valuePtr = value.c_str();
-		#endif
-	};
-
-	XMP_Node ( XMP_Node * _parent, const XMP_VarString & _name, XMP_OptionBits _options )
-		: options(_options), name(_name), parent(_parent)
-	{
-		#if XMP_DebugBuild
-			XMP_Assert ( (name.find ( ':' ) != XMP_VarString::npos) || (name == kXMP_ArrayItemName) ||
-			             (options & kXMP_SchemaNode) || (parent == 0) );
-			// *** _namePtr  = name.c_str();
-			// *** _valuePtr = value.c_str();
-		#endif
-	};
-	
-	XMP_Node ( XMP_Node * _parent, XMP_StringPtr _name, XMP_StringPtr _value, XMP_OptionBits _options )
-		: options(_options), name(_name), value(_value), parent(_parent)
-	{
-		#if XMP_DebugBuild
-			XMP_Assert ( (name.find ( ':' ) != XMP_VarString::npos) || (name == kXMP_ArrayItemName) ||
-			             (options & kXMP_SchemaNode) || (parent == 0) );
-			// *** _namePtr  = name.c_str();
-			// *** _valuePtr = value.c_str();
-		#endif
-	};
-
-	XMP_Node ( XMP_Node * _parent, const XMP_VarString & _name, const XMP_VarString & _value, XMP_OptionBits _options )
-		: options(_options), name(_name), value(_value), parent(_parent)
-	{
-		#if XMP_DebugBuild
-			XMP_Assert ( (name.find ( ':' ) != XMP_VarString::npos) || (name == kXMP_ArrayItemName) ||
-			             (options & kXMP_SchemaNode) || (parent == 0) );
-			// *** _namePtr  = name.c_str();
-			// *** _valuePtr = value.c_str();
-		#endif
-	};
-	
-	void RemoveChildren()
-	{
-		for ( size_t i = 0, vLim = children.size(); i < vLim; ++i ) {
-			if ( children[i] != 0 ) delete children[i];
-		}
-		children.clear();
-	}
-	
-	void RemoveQualifiers()
-	{
-		for ( size_t i = 0, vLim = qualifiers.size(); i < vLim; ++i ) {
-			if ( qualifiers[i] != 0 ) delete qualifiers[i];
-		}
-		qualifiers.clear();
-	}
-	
-	void ClearNode()
-	{
-		options = 0;
-		name.erase();
-		value.erase();
-		this->RemoveChildren();
-		this->RemoveQualifiers();
-	}
-
-	virtual ~XMP_Node() { RemoveChildren(); RemoveQualifiers(); };
-
-private:
-	XMP_Node() : options(0), parent(0)	// ! Make sure parent pointer is always set.
-	{
-		#if XMP_DebugBuild
-			// *** _namePtr  = name.c_str();
-			// *** _valuePtr = value.c_str();
-		#endif
-	};
-
-};
-
-class XMP_AutoNode {	// Used to hold a child during subtree construction.
-public:
-	XMP_Node * nodePtr;
-	XMP_AutoNode() : nodePtr(0) {};
-	~XMP_AutoNode() { if ( nodePtr != 0 ) delete ( nodePtr ); nodePtr = 0; };
-	XMP_AutoNode ( XMP_Node * _parent, XMP_StringPtr _name, XMP_OptionBits _options )
-		: nodePtr ( new XMP_Node ( _parent, _name, _options ) ) {};
-	XMP_AutoNode ( XMP_Node * _parent, const XMP_VarString & _name, XMP_OptionBits _options )
-		: nodePtr ( new XMP_Node ( _parent, _name, _options ) ) {};
-	XMP_AutoNode ( XMP_Node * _parent, XMP_StringPtr _name, XMP_StringPtr _value, XMP_OptionBits _options )
-		: nodePtr ( new XMP_Node ( _parent, _name, _value, _options ) ) {};
-	XMP_AutoNode ( XMP_Node * _parent, const XMP_VarString & _name, const XMP_VarString & _value, XMP_OptionBits _options )
-		: nodePtr ( new XMP_Node ( _parent, _name, _value, _options ) ) {};
-};
-
-extern void ProcessRDF ( XMP_Node * xmpTree, const XML_Node & xmlTree, XMP_OptionBits options );
-
-// =================================================================================================
-
-#endif	// __XMPCore_Impl_hpp__
diff --git a/xmpsdk/src/XMPIterator.cpp b/xmpsdk/src/XMPIterator.cpp
deleted file mode 100644
index ea39602a..00000000
--- a/xmpsdk/src/XMPIterator.cpp
+++ /dev/null
@@ -1,736 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-
-#include "XMPIterator.hpp"
-
-#include <string>
-#include <stdio.h>	// For snprintf.
-
-#if XMP_WinBuild
-    #ifdef _MSC_VER
-        #pragma warning ( disable : 4702 )	// unreachable code
-        #pragma warning ( disable : 4800 )	// forcing value to bool 'true' or 'false' (performance warning)
-        #pragma warning ( disable : 4996 )	// '...' was declared deprecated
-    #endif
-#endif
-
-// =================================================================================================
-// Support Routines
-// =================================================================================================
-
-
-#ifndef TraceIterators
-	#define TraceIterators 0
-#endif
-
-#if TraceIterators
-	static const char * sStageNames[] = { "before", "self", "qualifiers", "children" };
-#endif
-
-static XMP_Node * sDummySchema = 0;	// ! Used for some ugliness with aliases.
-
-// -------------------------------------------------------------------------------------------------
-// AddSchemaProps
-// --------------
-//
-// Add the top level properties to the IterNode for a schema.
-
-static void
-AddSchemaProps ( IterInfo & info, IterNode & iterSchema, const XMP_Node * xmpSchema )
-{
-	UNUSED(info);
-	#if TraceIterators
-		printf ( "    Adding properties of %s\n", xmpSchema->name.c_str() );
-	#endif
-
-	for ( size_t propNum = 0, propLim = xmpSchema->children.size(); propNum != propLim; ++propNum ) {
-		const XMP_Node * xmpProp = xmpSchema->children[propNum];
-		// *** set the has-aliases bit when appropriate
-		iterSchema.children.push_back ( IterNode ( xmpProp->options, xmpProp->name, 0 ) );
-		#if TraceIterators
-			printf ( "        %s\n", xmpProp->name.c_str() );
-		#endif
-	}
-
-}	// AddSchemaProps
-
-// -------------------------------------------------------------------------------------------------
-// AddSchemaAliases
-// ----------------
-//
-// Add the aliases to the IterNode for a schema, if the corresponding actual exists.
-
-static void
-AddSchemaAliases ( IterInfo & info, IterNode & iterSchema, XMP_StringPtr schemaURI )
-{
-	
-	// We're showing the aliases also. Look them up by their namespace prefix. Yes, the alias map is
-	// sorted so we could process just that portion. But that takes more code and the extra speed
-	// isn't worth it. (Plus this way we avoid a dependence on the map implementation.) Lookup the
-	// XMP node from the alias, to make sure the actual exists.
-	
-	#if TraceIterators
-		printf ( "    Adding aliases\n", schemaURI );
-	#endif
-
-	XMP_StringPtr nsPrefix;
-	XMP_StringLen nsLen;
-	bool found = XMPMeta::GetNamespacePrefix ( schemaURI, &nsPrefix, &nsLen );
-	if ( ! found ) XMP_Throw ( "Unknown iteration namespace", kXMPErr_BadSchema );
-	
-	XMP_AliasMapPos currAlias = sRegisteredAliasMap->begin();
-	XMP_AliasMapPos endAlias  = sRegisteredAliasMap->end();
-	
-	for ( ; currAlias != endAlias; ++currAlias ) {
-		if ( XMP_LitNMatch ( currAlias->first.c_str(), nsPrefix, nsLen ) ) {
-			const XMP_Node * actualProp = FindConstNode ( &info.xmpObj->tree, currAlias->second );
-			if ( actualProp != 0 ) {
-				iterSchema.children.push_back ( IterNode ( (actualProp->options | kXMP_PropIsAlias), currAlias->first, 0 ) );
-				#if TraceIterators
-					printf ( "        %s  =>  %s\n", currAlias->first.c_str(), actualProp->name.c_str() );
-				#endif
-			}
-		}
-	}
-
-}	// AddSchemaAliases
-
-// -------------------------------------------------------------------------------------------------
-// AddNodeOffspring
-// ----------------
-//
-// Add the immediate children and qualifiers to an IterNode.
-
-static void
-AddNodeOffspring ( IterInfo & info, IterNode & iterParent, const XMP_Node * xmpParent )
-{
-	XMP_VarString currPath ( iterParent.fullPath );
-	size_t        leafOffset = iterParent.fullPath.size();
-	
-	if ( (! xmpParent->qualifiers.empty()) && (! (info.options & kXMP_IterOmitQualifiers)) ) {
-
-		#if TraceIterators
-			printf ( "    Adding qualifiers of %s\n", currPath.c_str() );
-		#endif
-
-		currPath += "/?";	// All qualifiers are named and use paths like "Prop/?Qual".
-		leafOffset += 2;
-		
-		for ( size_t qualNum = 0, qualLim = xmpParent->qualifiers.size(); qualNum != qualLim; ++qualNum ) {
-			const XMP_Node * xmpQual = xmpParent->qualifiers[qualNum];
-			currPath += xmpQual->name;
-			iterParent.qualifiers.push_back ( IterNode ( xmpQual->options, currPath, leafOffset ) );
-			currPath.erase ( leafOffset );
-			#if TraceIterators
-				printf ( "        %s\n", xmpQual->name.c_str() );
-			#endif
-		}
-		
-		leafOffset -= 2;
-		currPath.erase ( leafOffset );
-
-	}
-
-	if ( ! xmpParent->children.empty() ) {
-	
-		#if TraceIterators
-			printf ( "    Adding children of %s\n", currPath.c_str() );
-		#endif
-
-		XMP_Assert ( xmpParent->options & kXMP_PropCompositeMask );
-		
-		if ( xmpParent->options & kXMP_PropValueIsStruct ) {
-			currPath += '/';
-			leafOffset += 1;
-		}
-		
-		for ( size_t childNum = 0, childLim = xmpParent->children.size(); childNum != childLim; ++childNum ) {
-			const XMP_Node * xmpChild = xmpParent->children[childNum];
-			if ( ! (xmpParent->options & kXMP_PropValueIsArray) ) {
-				currPath += xmpChild->name;
-			} else {
-				char buffer [32];	// AUDIT: Using sizeof(buffer) below for snprintf length is safe.
-				snprintf ( buffer, sizeof(buffer), "[%lu]", static_cast<unsigned long>(childNum+1) );	// ! XPath indices are one-based.
-				currPath += buffer;
-			}
-			iterParent.children.push_back ( IterNode ( xmpChild->options, currPath, leafOffset ) );
-			currPath.erase ( leafOffset );
-			#if TraceIterators
-				printf ( "        %s\n", (iterParent.children.back().fullPath.c_str() + leafOffset) );
-			#endif
-		}
-	
-	}
-
-}	// AddNodeOffspring
-
-// -------------------------------------------------------------------------------------------------
-// SetCurrSchema
-// -------------
-
-static inline void
-SetCurrSchema ( IterInfo & info, XMP_StringPtr schemaName )
-{
-
-	info.currSchema = schemaName;
-	#if 0	// *** XMP_DebugBuild
-		info._schemaPtr = info.currSchema.c_str();
-	#endif
-
-}	// SetCurrSchema
-
-static inline void
-SetCurrSchema ( IterInfo & info, XMP_VarString & schemaName )
-{
-
-	info.currSchema = schemaName;
-	#if 0	// *** XMP_DebugBuild
-		info._schemaPtr = info.currSchema.c_str();
-	#endif
-
-}	// SetCurrSchema
-
-// -------------------------------------------------------------------------------------------------
-// AdvanceIterPos
-// --------------
-//
-// Adjust currPos and possibly endPos for the next step in a pre-order depth-first traversal. The
-// current node has just been visited, move on to its qualifiers, children, then siblings, or back
-// up to an ancestor. AdvanceIterPos either moves to a property or qualifier node that can be
-// visited, or to the end of the entire iteration.
-
-static void
-AdvanceIterPos ( IterInfo & info )
-{
-	// -------------------------------------------------------------------------------------------
-	// Keep looking until we find a node to visit or the end of everything. The first time through
-	// the current node will exist, we just visited it. But we have to keep looking if the current
-	// node was the last of its siblings or is an empty schema.
-	
-	// ! It is possible that info.currPos == info.endPos on entry. Don't dereference info.currPos yet!
-
-	while ( true ) {
-	
-		if ( info.currPos == info.endPos ) {
-		
-			// ------------------------------------------------------------------------------------
-			// At the end of a set of siblings, move up to an ancestor. We've either just finished
-			// the qualifiers and will move to the children, or have just finished the children and
-			// will move on to the next sibling.
-			
-			if ( info.ancestors.empty() ) break;	// We're at the end of the schema list.
-
-			IterPosPair & parent = info.ancestors.back();
-			info.currPos = parent.first;
-			info.endPos  = parent.second;
-			info.ancestors.pop_back();
-			
-			#if TraceIterators
-				printf ( "    Moved up to %s, stage = %s\n",
-				         info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage] );
-			#endif
-		
-		} else {
-			
-			// -------------------------------------------------------------------------------------------
-			// Decide what to do with this iteration node based on its state. Don't use a switch statement,
-			// some of the cases want to break from the loop. A break in a switch just exits the case.
-			
-			#if TraceIterators
-				printf ( "    Moving from %s, stage = %s\n",
-				         info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage] );
-			#endif
-			
-			if ( info.currPos->visitStage == kIter_BeforeVisit ) {		// Visit this node now.
-				if ( info.currPos->options & kXMP_SchemaNode ) SetCurrSchema ( info, info.currPos->fullPath );
-				break;
-			}
-
-			if ( info.currPos->visitStage == kIter_VisitSelf ) {		// Just finished visiting the value portion.
-				info.currPos->visitStage = kIter_VisitQualifiers;		// Start visiting the qualifiers.
-				if ( ! info.currPos->qualifiers.empty() ) {
-					info.ancestors.push_back ( IterPosPair ( info.currPos, info.endPos ) );
-					info.endPos  = info.currPos->qualifiers.end();		// ! Set the parent's endPos before changing currPos!
-					info.currPos = info.currPos->qualifiers.begin();
-					break;
-				}
-			}
-
-			if ( info.currPos->visitStage == kIter_VisitQualifiers ) {	// Just finished visiting the qualifiers.
-				info.currPos->qualifiers.clear();
-				info.currPos->visitStage = kIter_VisitChildren;			// Start visiting the children.
-				if ( ! info.currPos->children.empty() ) {
-					info.ancestors.push_back ( IterPosPair ( info.currPos, info.endPos ) );
-					info.endPos  = info.currPos->children.end();		// ! Set the parent's endPos before changing currPos!
-					info.currPos = info.currPos->children.begin();
-					break;
-				}
-			}
-
-			if ( info.currPos->visitStage == kIter_VisitChildren ) {	// Just finished visiting the children.
-				info.currPos->children.clear();
-				++info.currPos;											// Move to the next sibling.
-				continue;
-			}
-			
-			#if TraceIterators
-				if ( info.currPos != info.endPos ) {
-					printf ( "    Moved to %s, stage = %s\n",
-					         info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage] );
-				}
-			#endif
-			
-		}
-
-	}	// Loop to find the next node.
-	
-	XMP_Assert ( (info.currPos == info.endPos) || (info.currPos->visitStage == kIter_BeforeVisit) );
-
-}	// AdvanceIterPos
-
-// -------------------------------------------------------------------------------------------------
-// GetNextXMPNode
-// --------------
-//
-// Used by XMPIterator::Next to obtain the next XMP node, ignoring the kXMP_IterJustLeafNodes flag.
-// This isolates some messy code, allowing a clean loop in Next if kXMP_IterJustLeafNodes is set.
-
-static const XMP_Node *
-GetNextXMPNode ( IterInfo & info )
-{
-	const XMP_Node * xmpNode = 0;
-
-	// ----------------------------------------------------------------------------------------------
-	// On entry currPos points to an iteration node whose state is either before-visit or visit-self.
-	// If it is before-visit then we will return that node's value part now. If it is visit-self it
-	// means the previous iteration returned the value portion of that node, so we can advance to the
-	// next node in the iteration tree. Then we find the corresponding XMP node, allowing for the XMP
-	// tree to have been modified since that part of the iteration tree was constructed.
-	
-	// ! NOTE: Supporting aliases throws in some nastiness with schemas. There might not be any XMP
-	// ! node for the schema, but we still have to visit it because of possible aliases. The static
-	// ! sDummySchema is returned if there is no real schema node.
-
-	if ( info.currPos->visitStage != kIter_BeforeVisit ) AdvanceIterPos ( info );
-	
-	bool isSchemaNode = false;
-	XMP_ExpandedXPath expPath;	// Keep outside the loop to avoid constant construct/destruct.
-	
-	while ( info.currPos != info.endPos ) {
-
-		isSchemaNode = XMP_NodeIsSchema ( info.currPos->options );
-		if ( isSchemaNode ) {
-			SetCurrSchema ( info, info.currPos->fullPath );
-			xmpNode = FindConstSchema ( &info.xmpObj->tree, info.currPos->fullPath.c_str() );
-			if ( xmpNode == 0 ) xmpNode = sDummySchema;
-		} else {
-			ExpandXPath ( info.currSchema.c_str(), info.currPos->fullPath.c_str(), &expPath );
-			xmpNode = FindConstNode ( &info.xmpObj->tree, expPath );
-		}
-		if ( xmpNode != 0 ) break;	// Exit the loop, we found a live XMP node.
-
-		info.currPos->visitStage = kIter_VisitChildren;	// Make AdvanceIterPos move to the next sibling.
-		info.currPos->children.clear();
-		info.currPos->qualifiers.clear();
-		AdvanceIterPos ( info );
-
-	}
-
-	if ( info.currPos == info.endPos ) return 0;
-	
-	// -------------------------------------------------------------------------------------------
-	// Now we've got the iteration node and corresponding XMP node. Add the iteration children for
-	// structs and arrays. The children of schema were added when the iterator was constructed.
-
-	XMP_Assert ( info.currPos->visitStage == kIter_BeforeVisit );
-
-	if ( info.currPos->visitStage == kIter_BeforeVisit ) {
-		if ( (! isSchemaNode) && (! (info.options & kXMP_IterJustChildren)) ) {
-			AddNodeOffspring ( info, *info.currPos, xmpNode );
-		}
-		info.currPos->visitStage = kIter_VisitSelf;
-	}
-	
-	return xmpNode;
-
-}	// GetNextXMPNode
-
-// =================================================================================================
-// Init/Term
-// =================================================================================================
-
-// -------------------------------------------------------------------------------------------------
-// Initialize
-// ----------
-
-/* class static */ bool
-XMPIterator::Initialize()
-{
-	sDummySchema = new XMP_Node ( 0, "dummy:schema/", kXMP_SchemaNode);
-	return true;
-	
-}	// Initialize
-
-// -------------------------------------------------------------------------------------------------
-// Terminate
-// ----------
-
-/* class static */ void
-XMPIterator::Terminate() RELEASE_NO_THROW
-{
-	delete ( sDummySchema );
-	sDummySchema = 0;
-	return;
-	
-}	// Terminate
-
-// -------------------------------------------------------------------------------------------------
-// Unlock
-// ------
-
-void
-XMPIterator::Unlock	( XMP_OptionBits options )
-{
-	UNUSED(options);
-
-	XMPMeta::Unlock ( 0 );
-	
-}	// Unlock
-
-// =================================================================================================
-// Constructors
-// =================================================================================================
-
-// -------------------------------------------------------------------------------------------------
-// XMPIterator
-// -----------
-//
-// Constructor for iterations over the nodes in an XMPMeta object. This builds a tree of iteration
-// nodes that caches the existing node names of the XMPMeta object. The iteration tree is a partial
-// replica of the XMPMeta tree. The initial iteration tree normally has just the root node, all of
-// the schema nodes for a full object iteration. Lower level nodes (children and qualifiers) are 
-// added when the parent is visited. If the kXMP_IterJustChildren option is passed then the initial
-// iterator includes the children and the parent is marked as done. The iteration tree nodes are
-// pruned when they are no longer needed. 
-
-XMPIterator::XMPIterator ( const XMPMeta & xmpObj,
-						   XMP_StringPtr   schemaNS,
-						   XMP_StringPtr   propName,
-						   XMP_OptionBits  options ) : clientRefs(0), info(IterInfo(options,&xmpObj))
-{
-	if ( (options & kXMP_IterClassMask) != kXMP_IterProperties ) {
-		XMP_Throw ( "Unsupported iteration kind", kXMPErr_BadOptions );
-	}
-	
-	// *** Lock the XMPMeta object if we ever stop using a full DLL lock.
-
-	if ( *propName != 0 ) {
-
-		// An iterator rooted at a specific node.
-
-		#if TraceIterators
-			printf ( "\nNew XMP property iterator for \"%s\", options = %X\n    Schema = %s, root = %s\n",
-			         xmpObj.tree.name.c_str(), options, schemaNS, propName );
-		#endif
-		
-		XMP_ExpandedXPath propPath;
-		ExpandXPath ( schemaNS, propName, &propPath );
-		XMP_Node * propNode = FindConstNode ( &xmpObj.tree, propPath );	// If not found get empty iteration.
-		
-		if ( propNode != 0 ) {
-
-			XMP_VarString rootName ( propPath[1].step );	// The schema is [0].
-			for ( size_t i = 2; i < propPath.size(); ++i ) {
-				XMP_OptionBits stepKind = GetStepKind ( propPath[i].options );
-				if ( stepKind <= kXMP_QualifierStep ) rootName += '/';
-				rootName += propPath[i].step;
-			}
-
-			propName = rootName.c_str();
-			size_t leafOffset = rootName.size();
-			while ( (leafOffset > 0) && (propName[leafOffset] != '/') && (propName[leafOffset] != '[') ) --leafOffset;
-			if ( propName[leafOffset] == '/' ) ++leafOffset;
-
-			info.tree.children.push_back ( IterNode ( propNode->options, propName, leafOffset ) );
-			SetCurrSchema ( info, propPath[kSchemaStep].step.c_str() );
-			if ( info.options & kXMP_IterJustChildren ) {
-				AddNodeOffspring ( info, info.tree.children.back(), propNode );
-			}
-
-		}
-	
-	} else if ( *schemaNS != 0 ) {
-
-		// An iterator for all properties in one schema.
-		
-		#if TraceIterators
-			printf ( "\nNew XMP schema iterator for \"%s\", options = %X\n    Schema = %s\n",
-			         xmpObj.tree.name.c_str(), options, schemaNS );
-		#endif
-		
-		info.tree.children.push_back ( IterNode ( kXMP_SchemaNode, schemaNS, 0 ) );
-		IterNode & iterSchema = info.tree.children.back();
-		
-		XMP_Node * xmpSchema = FindConstSchema ( &xmpObj.tree, schemaNS );
-		if ( xmpSchema != 0 ) AddSchemaProps ( info, iterSchema, xmpSchema );
-		
-		if ( info.options & kXMP_IterIncludeAliases ) AddSchemaAliases ( info, iterSchema, schemaNS );
-		
-		if ( iterSchema.children.empty() ) {
-			info.tree.children.pop_back();	// No properties, remove the schema node.
-		} else {
-			SetCurrSchema ( info, schemaNS );
-		}
-	
-	} else {
-
-		// An iterator for all properties in all schema. First add schema that exist (have children),
-		// adding aliases from them if appropriate. Then add schema that have no actual properties
-		// but do have aliases to existing properties, if we're including aliases in the iteration.
-		
-		#if TraceIterators
-			printf ( "\nNew XMP tree iterator for \"%s\", options = %X\n",
-			         xmpObj.tree.name.c_str(), options );
-		#endif
-		
-		// First pick up the schema that exist.
-		
-		for ( size_t schemaNum = 0, schemaLim = xmpObj.tree.children.size(); schemaNum != schemaLim; ++schemaNum ) {
-
-			const XMP_Node * xmpSchema = xmpObj.tree.children[schemaNum];
-			info.tree.children.push_back ( IterNode ( kXMP_SchemaNode, xmpSchema->name, 0 ) );
-			IterNode & iterSchema = info.tree.children.back();
-
-			if ( ! (info.options & kXMP_IterJustChildren) ) {
-				AddSchemaProps ( info, iterSchema, xmpSchema );
-				if ( info.options & kXMP_IterIncludeAliases ) AddSchemaAliases ( info, iterSchema, xmpSchema->name.c_str() );
-				if ( iterSchema.children.empty() ) info.tree.children.pop_back();	// No properties, remove the schema node.
-			}
-
-		}
-		
-		if ( info.options & kXMP_IterIncludeAliases ) {
-
-			// Add the schema that only have aliases. The most convenient, and safest way, is to go
-			// through the registered namespaces, see if it exists, and let AddSchemaAliases do its
-			// thing if not. Don't combine with the above loop, it is nicer to have the "real" stuff
-			// be in storage order (not subject to the namespace map order).
-			
-			// ! We don't do the kXMP_IterJustChildren handing in the same way here as above. The
-			// ! existing schema (presumably) have actual children. We need to call AddSchemaAliases
-			// ! here to determine if the namespace has any aliases to existing properties. We then
-			// ! strip the children if necessary.
-
-			XMP_cStringMapPos currNS = sNamespaceURIToPrefixMap->begin();
-			XMP_cStringMapPos endNS  = sNamespaceURIToPrefixMap->end();
-			for ( ; currNS != endNS; ++currNS ) {
-				XMP_StringPtr schemaName = currNS->first.c_str();
-				if ( FindConstSchema ( &xmpObj.tree, schemaName ) != 0 ) continue;
-				info.tree.children.push_back ( IterNode ( kXMP_SchemaNode, schemaName, 0 ) );
-				IterNode & iterSchema = info.tree.children.back();
-				AddSchemaAliases ( info, iterSchema, schemaName );
-				if ( iterSchema.children.empty() ) {
-					info.tree.children.pop_back();	// No aliases, remove the schema node.
-				} else if ( info.options & kXMP_IterJustChildren ) {
-					iterSchema.children.clear();	// Get rid of the children.
-				}
-			}
-
-		}
-
-	}
-	
-	// Set the current iteration position to the first node to be visited.
-	
-	info.currPos = info.tree.children.begin();
-	info.endPos  = info.tree.children.end();
-	
-	if ( (info.options & kXMP_IterJustChildren) && (info.currPos != info.endPos) && (*schemaNS != 0) ) {
-		info.currPos->visitStage = kIter_VisitSelf;
-	}
-
-	#if TraceIterators
-		if ( info.currPos == info.endPos ) {
-			printf ( "    ** Empty iteration **\n" );
-		} else {
-			printf ( "    Initial node %s, stage = %s, iterator @ %.8X\n",
-			         info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage], this );
-		}
-	#endif
-	
-}	// XMPIterator for XMPMeta objects
-
-// -------------------------------------------------------------------------------------------------
-// XMPIterator
-// -----------
-//
-// Constructor for iterations over global tables such as registered namespaces or aliases.
-
-XMPIterator::XMPIterator ( XMP_StringPtr  /*schemaNS*/,
-                           XMP_StringPtr  /*propName*/,
-                           XMP_OptionBits options ) : clientRefs(0), info(IterInfo(options,0))
-{
-
-	XMP_Throw ( "Unimplemented XMPIterator constructor for global tables", kXMPErr_Unimplemented );
-
-}	// XMPIterator for global tables
-
-// -------------------------------------------------------------------------------------------------
-// ~XMPIterator
-// -----------
-
-XMPIterator::~XMPIterator() RELEASE_NO_THROW
-{
-	XMP_Assert ( this->clientRefs <= 0 );
-	// Let everything else default.
-	
-}	// ~XMPIterator
-
-// =================================================================================================
-// Iteration Methods
-// =================================================================================================
-
-// -------------------------------------------------------------------------------------------------
-// Next
-// ----
-//
-// Do a preorder traversal of the cached nodes.
-
-// *** Need to document the relationships between currPos, endPos, and visitStage.
-
-bool
-XMPIterator::Next ( XMP_StringPtr *	 schemaNS,
-					XMP_StringLen *	 nsSize,
-					XMP_StringPtr *	 propPath,
-					XMP_StringLen *	 pathSize,
-					XMP_StringPtr *	 propValue,
-					XMP_StringLen *	 valueSize,
-					XMP_OptionBits * propOptions )
-{
-	// *** Lock the XMPMeta object if we ever stop using a full DLL lock.
-	
-	// ! NOTE: Supporting aliases throws in some nastiness with schemas. There might not be any XMP
-	// ! node for the schema, but we still have to visit it because of possible aliases.
-	
-	if ( info.currPos == info.endPos ) return false;	// Happens at the start of an empty iteration.
-	
-	#if TraceIterators
-		printf ( "Next iteration from %s, stage = %s, iterator @ %.8X\n",
-			     info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage], this );
-	#endif
-	
-	const XMP_Node * xmpNode = GetNextXMPNode ( info );
-	if ( xmpNode == 0 ) return false;
-	bool isSchemaNode = XMP_NodeIsSchema ( info.currPos->options );
-	
-	if ( info.options & kXMP_IterJustLeafNodes ) {
-		while ( isSchemaNode || (! xmpNode->children.empty()) ) {
-			info.currPos->visitStage = kIter_VisitQualifiers;	// Skip to this node's children.
-			xmpNode = GetNextXMPNode ( info );
-			if ( xmpNode == 0 ) return false;
-			isSchemaNode = XMP_NodeIsSchema ( info.currPos->options );
-		}
-	}
-	
-	*schemaNS = info.currSchema.c_str();
-	*nsSize   = info.currSchema.size();
-
-	*propOptions = info.currPos->options;
-
-	*propPath  = "";
-	*pathSize  = 0;
-	*propValue = "";
-	*valueSize = 0;
-	
-	if ( ! (*propOptions & kXMP_SchemaNode) ) {
-
-		*propPath = info.currPos->fullPath.c_str();
-		*pathSize = info.currPos->fullPath.size();
-		if ( info.options & kXMP_IterJustLeafName ) {
-			*propPath += info.currPos->leafOffset;
-			*pathSize -= info.currPos->leafOffset;
-		}
-		
-		if ( ! (*propOptions & kXMP_PropCompositeMask) ) {
-			*propValue = xmpNode->value.c_str();
-			*valueSize = xmpNode->value.size();
-		}
-
-	}
-	
-	#if TraceIterators
-		printf ( "    Next node %s, stage = %s\n",
-			     info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage] );
-	#endif
-	
-	return true;
-
-}	// Next
-
-// -------------------------------------------------------------------------------------------------
-// Skip
-// ----
-//
-// Skip some portion of the traversal related to the last visited node. We skip either that node's
-// children, or those children and the previous node's siblings. The implementation might look a bit
-// awkward because info.currNode always points to the next node to be visited. We might already have
-// moved past the things to skip, e.g. if the previous node was simple and the last of its siblings.
-
-enum {
-	kXMP_ValidIterSkipOptions	= kXMP_IterSkipSubtree | kXMP_IterSkipSiblings
-};
-
-void
-XMPIterator::Skip ( XMP_OptionBits iterOptions )
-{
-//	if ( (info.currPos == kIter_NullPos) )  XMP_Throw ( "No prior postion to skip from", kXMPErr_BadIterPosition );
-	if ( iterOptions == 0 ) XMP_Throw ( "Must specify what to skip", kXMPErr_BadOptions );
-	if ( (iterOptions & ~kXMP_ValidIterSkipOptions) != 0 ) XMP_Throw ( "Undefined options", kXMPErr_BadOptions );
-
-	#if TraceIterators
-		printf ( "Skipping from %s, stage = %s, iterator @ %.8X",
-			     info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage], this );
-	#endif
-	
-	if ( iterOptions & kXMP_IterSkipSubtree ) {
-		#if TraceIterators
-			printf ( ", mode = subtree\n" );
-		#endif
-		info.currPos->visitStage = kIter_VisitChildren;
-	} else if ( iterOptions & kXMP_IterSkipSiblings ) {
-		#if TraceIterators
-			printf ( ", mode = siblings\n" );
-		#endif
-		info.currPos = info.endPos;
-		AdvanceIterPos ( info );
-	}
-	#if TraceIterators
-		printf ( "    Skipped to %s, stage = %s\n",
-			     info.currPos->fullPath.c_str(), sStageNames[info.currPos->visitStage] );
-	#endif
-	
-
-}	// Skip
-
-// -------------------------------------------------------------------------------------------------
-// UnlockIter
-// ----------
-
-void
-XMPIterator::UnlockIter	( XMP_OptionBits options )
-{
-	UNUSED(options);
-
-	XMPMeta::Unlock ( 0 );
-	
-}	// UnlockIter
-
-// =================================================================================================
diff --git a/xmpsdk/src/XMPIterator.hpp b/xmpsdk/src/XMPIterator.hpp
deleted file mode 100644
index b72b9753..00000000
--- a/xmpsdk/src/XMPIterator.hpp
+++ /dev/null
@@ -1,148 +0,0 @@
-#ifndef __XMPIterator_hpp__
-#define __XMPIterator_hpp__
-
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"
-#include "XMP_Const.h"
-#include "XMPMeta.hpp"
-
-// =================================================================================================
-
-struct IterNode;
-typedef std::vector < IterNode >	IterOffspring;
-typedef IterOffspring::iterator		IterPos;
-
-typedef std::pair < IterPos, IterPos > IterPosPair;
-typedef std::vector < IterPosPair >	IterPosStack;
-
-enum {	// Values for the visitStage field, used to decide how to proceed past a node.
-	kIter_BeforeVisit		= 0,	// Have not visited this node at all.
-	kIter_VisitSelf			= 1,	// Have visited this node and returned its value/options portion.
-	kIter_VisitQualifiers	= 2,	// In the midst of visiting this node's qualifiers.
-	kIter_VisitChildren		= 3		// In the midst of visiting this node's children.
-};
-
-struct IterNode {
-
-	XMP_OptionBits	options;
-	XMP_VarString	fullPath;
-	size_t			leafOffset;
-	IterOffspring	children, qualifiers;
-	XMP_Uns8		visitStage;
-	#if 0	// *** XMP_DebugBuild
-		XMP_StringPtr	_pathPtr, _leafPtr;	// *** Not working, need operator=?
-	#endif
-
-	IterNode() : options(0), leafOffset(0), visitStage(kIter_BeforeVisit)
-	{
-		#if 0	// *** XMP_DebugBuild
-			_pathPtr = _leafPtr = 0;
-		#endif
-	};
-
-	IterNode ( XMP_OptionBits _options, const XMP_VarString& _fullPath, size_t _leafOffset )
-			 : options(_options), fullPath(_fullPath), leafOffset(_leafOffset), visitStage(kIter_BeforeVisit)
-	{
-		#if 0	// *** XMP_DebugBuild
-			_pathPtr = fullPath.c_str();
-			_leafPtr = _pathPtr + leafOffset;
-		#endif
-	};
-
-};
-
-struct IterInfo {
-
-	XMP_OptionBits	options;
-	const XMPMeta *	xmpObj;
-	XMP_VarString	currSchema;
-	IterPos			currPos, endPos;
-	IterPosStack	ancestors;
-	IterNode 		tree;
-	#if 0	// *** XMP_DebugBuild
-		XMP_StringPtr	_schemaPtr;	// *** Not working, need operator=?
-	#endif
-
-	IterInfo() : options(0), xmpObj(0)
-	{
-		#if 0	// *** XMP_DebugBuild
-			_schemaPtr = 0;
-		#endif
-	};
-
-	IterInfo ( XMP_OptionBits _options, const XMPMeta * _xmpObj ) : options(_options), xmpObj(_xmpObj)
-	{
-		#if 0	// *** XMP_DebugBuild
-			_schemaPtr = 0;
-		#endif
-	};
-
-};
-
-// =================================================================================================
-
-class XMPIterator {
-public:
-	
-	static bool
-	Initialize();	// ! For internal use only!
-	
-	static void
-	Terminate() RELEASE_NO_THROW;	// ! For internal use only!
-
-	static void
-	Unlock ( XMP_OptionBits options );
-
-	XMPIterator ( const XMPMeta & xmpObj,	// Construct a property iterator.
-				  XMP_StringPtr	  schemaNS,
-				  XMP_StringPtr	  propName,
-				  XMP_OptionBits  options );
-
-	XMPIterator	( XMP_StringPtr	 schemaNS,	// Construct a table iterator.
-				  XMP_StringPtr	 propName,
-				  XMP_OptionBits options );
-
-	virtual ~XMPIterator() RELEASE_NO_THROW;
-
-	bool
-	Next ( XMP_StringPtr *  schemaNS,
-		   XMP_StringLen *  nsSize,
-		   XMP_StringPtr *  propPath,
-		   XMP_StringLen *  pathSize,
-		   XMP_StringPtr *  propValue,
-		   XMP_StringLen *  valueSize,
-		   XMP_OptionBits * propOptions );
-
-	void
-	Skip ( XMP_OptionBits options );
-
-	void
-	UnlockIter ( XMP_OptionBits options );
-
-	// ! Expose so that wrappers and file static functions can see the data.
-
-	XMP_Int32 clientRefs;	// ! Must be signed to allow decrement from 0.
-	IterInfo info;
-
-private:
-
-	// ! These are hidden on purpose:
-	XMPIterator() : clientRefs(0)
-		{ XMP_Throw ( "Call to hidden constructor", kXMPErr_InternalFailure ); };
-	XMPIterator ( const XMPIterator & /* original */ ) : clientRefs(0)
-		{ XMP_Throw ( "Call to hidden constructor", kXMPErr_InternalFailure ); };
-	void operator= ( const XMPIterator & /* rhs */ )
-		{ XMP_Throw ( "Call to hidden operator=", kXMPErr_InternalFailure ); };
-
-};
-
-// =================================================================================================
-
-#endif	// __XMPIterator_hpp__
diff --git a/xmpsdk/src/XMPMeta-GetSet.cpp b/xmpsdk/src/XMPMeta-GetSet.cpp
deleted file mode 100644
index 9972f9e6..00000000
--- a/xmpsdk/src/XMPMeta-GetSet.cpp
+++ /dev/null
@@ -1,1212 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-//
-// Adobe patent application tracking #P435, entitled 'Unique markers to simplify embedding data of
-// one format in a file with a different format', inventors: Sean Parent, Greg Gilley.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-
-#include "XMPMeta.hpp"
-#include "XMPIterator.hpp"
-#include "XMPUtils.hpp"
-
-#include "XMP_Version.h"
-#include "UnicodeInlines.incl_cpp"
-#include "UnicodeConversions.hpp"
-#include "ExpatAdapter.hpp"
-
-#if XMP_DebugBuild
-	#include <iostream>
-#endif
-
-using namespace std;
-
-#if XMP_WinBuild
-    #ifdef _MSC_VER
-        #pragma warning ( disable : 4533 )	// initialization of '...' is skipped by 'goto ...'
-        #pragma warning ( disable : 4702 )	// unreachable code
-        #pragma warning ( disable : 4800 )	// forcing value to bool 'true' or 'false' (performance warning)
-    #endif
-#endif
-
-
-// *** Use the XMP_PropIsXyz (Schema, Simple, Struct, Array, ...) macros
-// *** Add debug codegen checks, e.g. that typical masking operations really work
-// *** Change all uses of strcmp and strncmp to XMP_LitMatch and XMP_LitNMatch
-
-
-// =================================================================================================
-// Local Types and Constants
-// =========================
-
-typedef unsigned char XMP_CLTMatch;
-
-enum {	// Values for XMP_CLTMatch.
-	kXMP_CLT_NoValues,
-	kXMP_CLT_SpecificMatch,
-	kXMP_CLT_SingleGeneric,
-	kXMP_CLT_MultipleGeneric,
-	kXMP_CLT_XDefault,
-	kXMP_CLT_FirstItem
-};
-
-
-// =================================================================================================
-// Static Variables
-// ================
-
-
-// =================================================================================================
-// Local Utilities
-// ===============
-
-
-// -------------------------------------------------------------------------------------------------
-// SetNodeValue
-// ------------
-
-static inline void
-SetNodeValue ( XMP_Node * node, XMP_StringPtr value )
-{
-
-	#if XMP_DebugBuild	// ! Hack to force an assert.
-		if ( (node->name == "xmp:TestAssertNotify") && XMP_LitMatch ( value, "DoIt!" ) ) {
-			XMP_Assert ( node->name != "xmp:TestAssertNotify" );
-		}
-	#endif
-	
-	node->value = value;
-	
-	XMP_Uns8* chPtr = (XMP_Uns8*) node->value.c_str();	// Check for valid UTF-8, replace ASCII controls with a space.
-	while ( *chPtr != 0 ) {
-		while ( (*chPtr != 0) && (*chPtr < 0x80) ) {
-			if ( *chPtr < 0x20 ) {
-				if ( (*chPtr != kTab) && (*chPtr != kLF) && (*chPtr != kCR) ) *chPtr = 0x20;
-			} else if (*chPtr == 0x7F ) {
-				*chPtr = 0x20;
-			}
-			++chPtr;
-		}
-		XMP_Assert ( (*chPtr == 0) || (*chPtr >= 0x80) );
-		if ( *chPtr != 0 ) (void) GetCodePoint ( (const XMP_Uns8 **) &chPtr );	// Throws for bad UTF-8.
-	}
-
-	if ( XMP_PropIsQualifier(node->options) && (node->name == "xml:lang") ) NormalizeLangValue ( &node->value );
-
-	#if 0	// *** XMP_DebugBuild
-		node->_valuePtr = node->value.c_str();
-	#endif
-	
-}	// SetNodeValue
-
-
-// -------------------------------------------------------------------------------------------------
-// SetNode
-// -------
-//
-// The internals for SetProperty and related calls, used after the node is found or created.
-
-static void
-SetNode	( XMP_Node * node, XMP_StringPtr value, XMP_OptionBits options )
-{
-	if ( options & kXMP_DeleteExisting ) {
-		XMP_ClearOption ( options, kXMP_DeleteExisting );
-		node->options = options;
-		node->value.erase();
-		node->RemoveChildren();
-		node->RemoveQualifiers();
-	}
-	
-	node->options |= options;	// Keep options set by FindNode when creating a new node.
-
-	if ( value != 0 ) {
-	
-		// This is setting the value of a leaf node.
-		if ( node->options & kXMP_PropCompositeMask ) XMP_Throw ( "Composite nodes can't have values", kXMPErr_BadXPath );
-		XMP_Assert ( node->children.empty() );
-		SetNodeValue ( node, value );
-	
-	} else {
-	
-		// This is setting up an array or struct.
-		if ( ! node->value.empty() ) XMP_Throw ( "Composite nodes can't have values", kXMPErr_BadXPath );
-		if ( node->options & kXMP_PropCompositeMask ) {	// Can't change an array to a struct, or vice versa.
-			if ( (options & kXMP_PropCompositeMask) != (node->options & kXMP_PropCompositeMask) ) {
-				XMP_Throw ( "Requested and existing composite form mismatch", kXMPErr_BadXPath );
-			}
-		}
-		node->RemoveChildren();
-	
-	}
-	
-}	// SetNode
-
-
-// -------------------------------------------------------------------------------------------------
-// DoSetArrayItem
-// --------------
-
-static void
-DoSetArrayItem ( XMP_Node *		arrayNode,
-				 XMP_Index		itemIndex,
-				 XMP_StringPtr	itemValue,
-				 XMP_OptionBits options )
-{
-	XMP_OptionBits itemLoc = options & kXMP_PropArrayLocationMask;
-	XMP_Index      arraySize = arrayNode->children.size();
-	
-	options &= ~kXMP_PropArrayLocationMask;
-	options = VerifySetOptions ( options, itemValue );
-	
-	// Now locate or create the item node and set the value. Note the index parameter is one-based!
-	// The index can be in the range [0..size+1] or "last", normalize it and check the insert flags.
-	// The order of the normalization checks is important. If the array is empty we end up with an
-	// index and location to set item size+1.
-	
-	XMP_Node * itemNode = 0;
-	
-	if ( itemIndex == kXMP_ArrayLastItem ) itemIndex = arraySize;
-	if ( (itemIndex == 0) && (itemLoc == kXMP_InsertAfterItem) ) {
-		itemIndex = 1;
-		itemLoc = kXMP_InsertBeforeItem;
-	}
-	if ( (itemIndex == arraySize) && (itemLoc == kXMP_InsertAfterItem) ) {
-		itemIndex += 1;
-		itemLoc = 0;
-	}
-	if ( (itemIndex == arraySize+1) && (itemLoc == kXMP_InsertBeforeItem) ) itemLoc = 0;
-	
-	if ( itemIndex == arraySize+1 ) {
-
-		if ( itemLoc != 0 ) XMP_Throw ( "Can't insert before or after implicit new item", kXMPErr_BadIndex );
-		itemNode = new XMP_Node ( arrayNode, kXMP_ArrayItemName, 0 );
-		arrayNode->children.push_back ( itemNode );
-
-	} else {
-
-		if ( (itemIndex < 1) || (itemIndex > arraySize) ) XMP_Throw ( "Array index out of bounds", kXMPErr_BadIndex );
-		--itemIndex;	// ! Convert the index to a C zero-based value!
-		if ( itemLoc == 0 ) {
-			itemNode = arrayNode->children[itemIndex];
-		} else {
-			XMP_NodePtrPos itemPos = arrayNode->children.begin() + itemIndex;
-			if ( itemLoc == kXMP_InsertAfterItem ) ++itemPos;
-			itemNode = new XMP_Node ( arrayNode, kXMP_ArrayItemName, 0 );
-			itemPos = arrayNode->children.insert ( itemPos, itemNode );
-		}
-
-	}
-	
-	SetNode ( itemNode, itemValue, options );
-	
-}	// DoSetArrayItem
-
-
-// -------------------------------------------------------------------------------------------------
-// ChooseLocalizedText
-// -------------------
-//
-// 1. Look for an exact match with the specific language.
-// 2. If a generic language is given, look for partial matches.
-// 3. Look for an "x-default" item.
-// 4. Choose the first item.
-
-static XMP_CLTMatch
-ChooseLocalizedText ( const XMP_Node *	 arrayNode,
-					  XMP_StringPtr		 genericLang,
-					  XMP_StringPtr		 specificLang,
-					  const XMP_Node * * itemNode )
-{
-	const XMP_Node * currItem = 0;
-	const size_t itemLim = arrayNode->children.size();
-	size_t itemNum;
-	
-	// See if the array has the right form. Allow empty alt arrays, that is what parsing returns.
-	// *** Should check alt-text bit when that is reliably maintained.
-
-	if ( ! ( XMP_ArrayIsAltText(arrayNode->options) ||
-	         (arrayNode->children.empty() && XMP_ArrayIsAlternate(arrayNode->options)) ) ) {
-		XMP_Throw ( "Localized text array is not alt-text", kXMPErr_BadXPath );
-	}
-	if ( arrayNode->children.empty() ) {
-		*itemNode = 0;
-		return kXMP_CLT_NoValues;
-	}
-
-	for ( itemNum = 0; itemNum < itemLim; ++itemNum ) {
-		currItem = arrayNode->children[itemNum];
-		if ( currItem->options & kXMP_PropCompositeMask ) {
-			XMP_Throw ( "Alt-text array item is not simple", kXMPErr_BadXPath );
-		}
-		if ( currItem->qualifiers.empty() || (currItem->qualifiers[0]->name != "xml:lang") ) {
-			XMP_Throw ( "Alt-text array item has no language qualifier", kXMPErr_BadXPath );
-		}
-	}
-
-	// Look for an exact match with the specific language.
-	for ( itemNum = 0; itemNum < itemLim; ++itemNum ) {
-		currItem = arrayNode->children[itemNum];
-		if ( currItem->qualifiers[0]->value == specificLang ) {
-			*itemNode = currItem;
-			return kXMP_CLT_SpecificMatch;
-		}
-	}
-	
-	if ( *genericLang != 0 ) {
-
-		// Look for the first partial match with the generic language.
-		const size_t genericLen = strlen ( genericLang );
-		for ( itemNum = 0; itemNum < itemLim; ++itemNum ) {
-			currItem = arrayNode->children[itemNum];
-			XMP_StringPtr currLang = currItem->qualifiers[0]->value.c_str();
-			const size_t currLangSize = currItem->qualifiers[0]->value.size();
-			if ( (currLangSize >= genericLen) &&
-				 XMP_LitNMatch ( currLang, genericLang, genericLen ) &&
-				 ((currLangSize == genericLen) || (currLang[genericLen] == '-')) ) {
-				*itemNode = currItem;
-				break;	// ! Don't return, need to look for other matches.
-			}
-		}
-
-		if ( itemNum < itemLim ) {
-			
-			// Look for a second partial match with the generic language.
-			for ( ++itemNum; itemNum < itemLim; ++itemNum ) {
-				currItem = arrayNode->children[itemNum];
-				XMP_StringPtr currLang = currItem->qualifiers[0]->value.c_str();
-				const size_t currLangSize = currItem->qualifiers[0]->value.size();
-				if ( (currLangSize >= genericLen) &&
-					 XMP_LitNMatch ( currLang, genericLang, genericLen ) &&
-					 ((currLangSize == genericLen) || (currLang[genericLen] == '-')) ) {
-					return kXMP_CLT_MultipleGeneric;	// ! Leave itemNode with the first partial match.
-				}
-			}
-			return kXMP_CLT_SingleGeneric;	// No second partial match was found.
-
-		}
-		
-	}
-	
-	// Look for an 'x-default' item.
-	for ( itemNum = 0; itemNum < itemLim; ++itemNum ) {
-		currItem = arrayNode->children[itemNum];
-		if ( currItem->qualifiers[0]->value == "x-default" ) {
-			*itemNode = currItem;
-			return kXMP_CLT_XDefault;
-		}
-	}
-	
-	// Everything failed, choose the first item.
-	*itemNode = arrayNode->children[0];
-	return kXMP_CLT_FirstItem;
-	
-}	// ChooseLocalizedText
-
-
-// -------------------------------------------------------------------------------------------------
-// AppendLangItem
-// --------------
-
-static void
-AppendLangItem ( XMP_Node * arrayNode, XMP_StringPtr itemLang, XMP_StringPtr itemValue )
-{
-	XMP_Node * newItem  = new XMP_Node ( arrayNode, kXMP_ArrayItemName, itemValue, (kXMP_PropHasQualifiers | kXMP_PropHasLang) );
-	XMP_Node * langQual = new XMP_Node ( newItem, "xml:lang", itemLang, kXMP_PropIsQualifier );
-	newItem->qualifiers.push_back ( langQual );
-
-	if ( (arrayNode->children.empty()) || (langQual->value != "x-default") ) {
-		arrayNode->children.push_back ( newItem );
-	} else {
-		arrayNode->children.insert ( arrayNode->children.begin(), newItem );
-	}
-
-}	// AppendLangItem
-
-
-// =================================================================================================
-// Class Methods
-// =============
-//
-//
-// =================================================================================================
-
-
-// -------------------------------------------------------------------------------------------------
-// GetProperty
-// -----------
-
-bool
-XMPMeta::GetProperty ( XMP_StringPtr	schemaNS,
-					   XMP_StringPtr	propName,
-					   XMP_StringPtr *	propValue,
-					   XMP_StringLen *	valueSize,
-					   XMP_OptionBits *	options ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (propValue != 0) && (valueSize != 0) && (options != 0) );	// Enforced by wrapper.
-
-	XMP_ExpandedXPath expPath;
-	ExpandXPath ( schemaNS, propName, &expPath );
-	
-	XMP_Node * propNode = FindConstNode ( &tree, expPath );
-	if ( propNode == 0 ) return false;
-	
-	*propValue = propNode->value.c_str();
-	*valueSize = propNode->value.size();
-	*options   = propNode->options;
-	
-	return true;
-	
-}	// GetProperty
-
-
-// -------------------------------------------------------------------------------------------------
-// GetArrayItem
-// ------------
-
-bool
-XMPMeta::GetArrayItem ( XMP_StringPtr	 schemaNS,
-						XMP_StringPtr	 arrayName,
-						XMP_Index		 itemIndex,
-						XMP_StringPtr *	 itemValue,
-						XMP_StringLen *	 valueSize,
-						XMP_OptionBits * options ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (arrayName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (itemValue != 0) && (valueSize != 0) && (options != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr itemPath;
-	XMP_StringLen pathLen;
-
-	XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath, &pathLen );
-	return GetProperty ( schemaNS, itemPath, itemValue, valueSize, options );
-
-}	// GetArrayItem
-
-
-// -------------------------------------------------------------------------------------------------
-// GetStructField
-// --------------
-
-bool
-XMPMeta::GetStructField	( XMP_StringPtr	   schemaNS,
-						  XMP_StringPtr	   structName,
-						  XMP_StringPtr	   fieldNS,
-						  XMP_StringPtr	   fieldName,
-						  XMP_StringPtr *  fieldValue,
-						  XMP_StringLen *  valueSize,
-						  XMP_OptionBits * options ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (fieldValue != 0) && (valueSize != 0) && (options != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr fieldPath;
-	XMP_StringLen pathLen;
-
-	XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen );
-	return GetProperty ( schemaNS, fieldPath, fieldValue, valueSize, options );
-
-}	// GetStructField
-
-
-// -------------------------------------------------------------------------------------------------
-// GetQualifier
-// ------------
-
-bool
-XMPMeta::GetQualifier ( XMP_StringPtr	 schemaNS,
-						XMP_StringPtr	 propName,
-						XMP_StringPtr	 qualNS,
-						XMP_StringPtr	 qualName,
-						XMP_StringPtr *	 qualValue,
-						XMP_StringLen *	 valueSize,
-						XMP_OptionBits * options ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (qualValue != 0) && (valueSize != 0) && (options != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr qualPath;
-	XMP_StringLen pathLen;
-
-	XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen );
-	return GetProperty ( schemaNS, qualPath, qualValue, valueSize, options );
-
-}	// GetQualifier
-
-
-// -------------------------------------------------------------------------------------------------
-// SetProperty
-// -----------
-
-// *** Should handle array items specially, calling SetArrayItem.
-
-void
-XMPMeta::SetProperty ( XMP_StringPtr  schemaNS,
-					   XMP_StringPtr  propName,
-					   XMP_StringPtr  propValue,
-					   XMP_OptionBits options )
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-
-	options = VerifySetOptions ( options, propValue );
-
-	XMP_ExpandedXPath expPath;
-	ExpandXPath ( schemaNS, propName, &expPath );
-
-	XMP_Node * propNode = FindNode ( &tree, expPath, kXMP_CreateNodes, options );
-	if ( propNode == 0 ) XMP_Throw ( "Specified property does not exist", kXMPErr_BadXPath );
-	
-	SetNode ( propNode, propValue, options );
-	
-}	// SetProperty
-
-
-// -------------------------------------------------------------------------------------------------
-// SetArrayItem
-// ------------
-
-void
-XMPMeta::SetArrayItem ( XMP_StringPtr  schemaNS,
-						XMP_StringPtr  arrayName,
-						XMP_Index	   itemIndex,
-						XMP_StringPtr  itemValue,
-						XMP_OptionBits options )
-{
-	XMP_Assert ( (schemaNS != 0) && (arrayName != 0) );	// Enforced by wrapper.
-
-	XMP_ExpandedXPath arrayPath;
-	ExpandXPath ( schemaNS, arrayName, &arrayPath );
-	XMP_Node * arrayNode = FindNode ( &tree, arrayPath, kXMP_ExistingOnly );	// Just lookup, don't try to create.
-	if ( arrayNode == 0 ) XMP_Throw ( "Specified array does not exist", kXMPErr_BadXPath );
-	
-	DoSetArrayItem ( arrayNode, itemIndex, itemValue, options );
-	
-}	// SetArrayItem
-
-
-// -------------------------------------------------------------------------------------------------
-// AppendArrayItem
-// ---------------
-
-void
-XMPMeta::AppendArrayItem ( XMP_StringPtr  schemaNS,
-						   XMP_StringPtr  arrayName,
-						   XMP_OptionBits arrayOptions,
-						   XMP_StringPtr  itemValue,
-						   XMP_OptionBits options )
-{
-	XMP_Assert ( (schemaNS != 0) && (arrayName != 0) );	// Enforced by wrapper.
-
-	arrayOptions = VerifySetOptions ( arrayOptions, 0 );
-	if ( (arrayOptions & ~kXMP_PropArrayFormMask) != 0 ) {
-		XMP_Throw ( "Only array form flags allowed for arrayOptions", kXMPErr_BadOptions );
-	}
-	
-	// Locate or create the array. If it already exists, make sure the array form from the options
-	// parameter is compatible with the current state.
-	
-	XMP_ExpandedXPath arrayPath;
-	ExpandXPath ( schemaNS, arrayName, &arrayPath );
-	XMP_Node * arrayNode = FindNode ( &tree, arrayPath, kXMP_ExistingOnly );	// Just lookup, don't try to create.
-	
-	if ( arrayNode != 0 ) {
-		// The array exists, make sure the form is compatible. Zero arrayForm means take what exists.
-		if ( ! (arrayNode->options & kXMP_PropValueIsArray) ) {
-			XMP_Throw ( "The named property is not an array", kXMPErr_BadXPath );
-		}
-		#if 0
-			// *** Disable for now. Need to do some general rethinking of semantic checks.
-			if ( (arrayOptions != 0) && (arrayOptions != (arrayNode->options & kXMP_PropArrayFormMask)) ) {
-				XMP_Throw ( "Mismatch of existing and specified array form", kXMPErr_BadOptions );
-			}
-		#endif
-	} else {
-		// The array does not exist, try to create it.
-		if ( arrayOptions == 0 ) XMP_Throw ( "Explicit arrayOptions required to create new array", kXMPErr_BadOptions );
-		arrayNode = FindNode ( &tree, arrayPath, kXMP_CreateNodes, arrayOptions );
-		if ( arrayNode == 0 ) XMP_Throw ( "Failure creating array node", kXMPErr_BadXPath );
-	}
-	
-	DoSetArrayItem ( arrayNode, kXMP_ArrayLastItem, itemValue, (options | kXMP_InsertAfterItem) );
-	
-}	// AppendArrayItem
-
-
-// -------------------------------------------------------------------------------------------------
-// SetStructField
-// --------------
-
-void
-XMPMeta::SetStructField	( XMP_StringPtr	 schemaNS,
-						  XMP_StringPtr	 structName,
-						  XMP_StringPtr	 fieldNS,
-						  XMP_StringPtr	 fieldName,
-						  XMP_StringPtr	 fieldValue,
-						  XMP_OptionBits options )
-{
-	XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	fieldPath;
-	XMP_StringLen	pathLen;
-
-	XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen );
-	SetProperty ( schemaNS, fieldPath, fieldValue, options );
-
-}	// SetStructField
-
-
-// -------------------------------------------------------------------------------------------------
-// SetQualifier
-// ------------
-
-void
-XMPMeta::SetQualifier ( XMP_StringPtr  schemaNS,
-						XMP_StringPtr  propName,
-						XMP_StringPtr  qualNS,
-						XMP_StringPtr  qualName,
-						XMP_StringPtr  qualValue,
-						XMP_OptionBits options )
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	qualPath;
-	XMP_StringLen	pathLen;
-
-	XMP_ExpandedXPath expPath;
-	ExpandXPath ( schemaNS, propName, &expPath );
-	XMP_Node * propNode = FindNode ( &tree, expPath, kXMP_ExistingOnly );
-	if ( propNode == 0 ) XMP_Throw ( "Specified property does not exist", kXMPErr_BadXPath );
-
-	XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen );
-	SetProperty ( schemaNS, qualPath, qualValue, options );
-
-}	// SetQualifier
-
-
-// -------------------------------------------------------------------------------------------------
-// DeleteProperty
-// --------------
-
-void
-XMPMeta::DeleteProperty	( XMP_StringPtr	schemaNS,
-						  XMP_StringPtr	propName )
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-
-	XMP_ExpandedXPath	expPath;
-	ExpandXPath ( schemaNS, propName, &expPath );
-	
-	XMP_NodePtrPos ptrPos;
-	XMP_Node * propNode = FindNode ( &tree, expPath, kXMP_ExistingOnly, kXMP_NoOptions, &ptrPos );
-	if ( propNode == 0 ) return;
-	XMP_Node * parentNode = propNode->parent;
-	
-	// Erase the pointer from the parent's vector, then delete the node and all below it.
-	
-	if ( ! (propNode->options & kXMP_PropIsQualifier) ) {
-
-		parentNode->children.erase ( ptrPos );
-		DeleteEmptySchema ( parentNode );
-
-	} else {
-
-		if ( propNode->name == "xml:lang" ) {
-			XMP_Assert ( parentNode->options & kXMP_PropHasLang );	// *** &= ~flag would be safer
-			parentNode->options ^= kXMP_PropHasLang;
-		} else if ( propNode->name == "rdf:type" ) {
-			XMP_Assert ( parentNode->options & kXMP_PropHasType );
-			parentNode->options ^= kXMP_PropHasType;
-		}
-
-		parentNode->qualifiers.erase ( ptrPos );
-		XMP_Assert ( parentNode->options & kXMP_PropHasQualifiers );
-		if ( parentNode->qualifiers.empty() ) parentNode->options ^= kXMP_PropHasQualifiers;
-
-	}
-	
-	delete propNode;	// ! The destructor takes care of the whole subtree.
-	
-}	// DeleteProperty
-
-
-// -------------------------------------------------------------------------------------------------
-// DeleteArrayItem
-// ---------------
-
-void
-XMPMeta::DeleteArrayItem ( XMP_StringPtr schemaNS,
-						   XMP_StringPtr arrayName,
-						   XMP_Index	 itemIndex )
-{
-	XMP_Assert ( (schemaNS != 0) && (arrayName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	itemPath;
-	XMP_StringLen	pathLen;
-
-	XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath, &pathLen );
-	DeleteProperty ( schemaNS, itemPath );
-
-}	// DeleteArrayItem
-
-
-// -------------------------------------------------------------------------------------------------
-// DeleteStructField
-// -----------------
-
-void
-XMPMeta::DeleteStructField ( XMP_StringPtr schemaNS,
-							 XMP_StringPtr structName,
-							 XMP_StringPtr fieldNS,
-							 XMP_StringPtr fieldName )
-{
-	XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	fieldPath;
-	XMP_StringLen	pathLen;
-
-	XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen );
-	DeleteProperty ( schemaNS, fieldPath );
-
-}	// DeleteStructField
-
-
-// -------------------------------------------------------------------------------------------------
-// DeleteQualifier
-// ---------------
-
-void
-XMPMeta::DeleteQualifier ( XMP_StringPtr schemaNS,
-						   XMP_StringPtr propName,
-						   XMP_StringPtr qualNS,
-						   XMP_StringPtr qualName )
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	qualPath;
-	XMP_StringLen	pathLen;
-
-	XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen );
-	DeleteProperty ( schemaNS, qualPath );
-
-}	// DeleteQualifier
-
-
-// -------------------------------------------------------------------------------------------------
-// DoesPropertyExist
-// -----------------
-
-bool
-XMPMeta::DoesPropertyExist ( XMP_StringPtr schemaNS,
-							 XMP_StringPtr propName ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-
-	XMP_ExpandedXPath	expPath;
-	ExpandXPath ( schemaNS, propName, &expPath );
-
-	XMP_Node * propNode = FindConstNode ( &tree, expPath );
-	return (propNode != 0);
-	
-}	// DoesPropertyExist
-
-
-// -------------------------------------------------------------------------------------------------
-// DoesArrayItemExist
-// ------------------
-
-bool
-XMPMeta::DoesArrayItemExist	( XMP_StringPtr	schemaNS,
-							  XMP_StringPtr	arrayName,
-							  XMP_Index		itemIndex ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (arrayName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	itemPath;
-	XMP_StringLen	pathLen;
-
-	XMPUtils::ComposeArrayItemPath ( schemaNS, arrayName, itemIndex, &itemPath, &pathLen );
-	return DoesPropertyExist ( schemaNS, itemPath );
-
-}	// DoesArrayItemExist
-
-
-// -------------------------------------------------------------------------------------------------
-// DoesStructFieldExist
-// --------------------
-
-bool
-XMPMeta::DoesStructFieldExist ( XMP_StringPtr schemaNS,
-								XMP_StringPtr structName,
-								XMP_StringPtr fieldNS,
-								XMP_StringPtr fieldName ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (structName != 0) && (fieldNS != 0) && (fieldName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	fieldPath;
-	XMP_StringLen	pathLen;
-
-	XMPUtils::ComposeStructFieldPath ( schemaNS, structName, fieldNS, fieldName, &fieldPath, &pathLen );
-	return DoesPropertyExist ( schemaNS, fieldPath );
-
-}	// DoesStructFieldExist
-
-
-// -------------------------------------------------------------------------------------------------
-// DoesQualifierExist
-// ------------------
-
-bool
-XMPMeta::DoesQualifierExist	( XMP_StringPtr	schemaNS,
-							  XMP_StringPtr	propName,
-							  XMP_StringPtr	qualNS,
-							  XMP_StringPtr	qualName ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) && (qualNS != 0) && (qualName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	qualPath;
-	XMP_StringLen	pathLen;
-
-	XMPUtils::ComposeQualifierPath ( schemaNS, propName, qualNS, qualName, &qualPath, &pathLen );
-	return DoesPropertyExist ( schemaNS, qualPath );
-
-}	// DoesQualifierExist
-
-
-// -------------------------------------------------------------------------------------------------
-// GetLocalizedText
-// ----------------
-
-bool
-XMPMeta::GetLocalizedText ( XMP_StringPtr	 schemaNS,
-							XMP_StringPtr	 arrayName,
-							XMP_StringPtr	 _genericLang,
-							XMP_StringPtr	 _specificLang,
-							XMP_StringPtr *	 actualLang,
-							XMP_StringLen *	 langSize,
-							XMP_StringPtr *	 itemValue,
-							XMP_StringLen *	 valueSize,
-							XMP_OptionBits * options ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (arrayName != 0) && (_genericLang != 0) && (_specificLang != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (actualLang != 0) && (langSize != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (itemValue != 0) && (valueSize != 0) && (options != 0) );	// Enforced by wrapper.
-
-	XMP_VarString zGenericLang  ( _genericLang );
-	XMP_VarString zSpecificLang ( _specificLang );
-	NormalizeLangValue ( &zGenericLang );
-	NormalizeLangValue ( &zSpecificLang );
-	
-	XMP_StringPtr genericLang  = zGenericLang.c_str();
-	XMP_StringPtr specificLang = zSpecificLang.c_str();
-	
-	XMP_ExpandedXPath arrayPath;
-	ExpandXPath ( schemaNS, arrayName, &arrayPath );
-	
-	const XMP_Node * arrayNode = FindConstNode ( &tree, arrayPath );	// *** This expand/find idiom is used in 3 Getters.
-	if ( arrayNode == 0 ) return false;			// *** Should extract it into a local utility.
-	
-	XMP_CLTMatch match;
-	const XMP_Node * itemNode;
-	
-	match = ChooseLocalizedText ( arrayNode, genericLang, specificLang, &itemNode );
-	if ( match == kXMP_CLT_NoValues ) return false;
-	
-	*actualLang = itemNode->qualifiers[0]->value.c_str();
-	*langSize   = itemNode->qualifiers[0]->value.size();
-	*itemValue  = itemNode->value.c_str();
-	*valueSize  = itemNode->value.size();
-	*options    = itemNode->options;
-
-	return true;
-	
-}	// GetLocalizedText
-
-
-// -------------------------------------------------------------------------------------------------
-// SetLocalizedText
-// ----------------
-
-void
-XMPMeta::SetLocalizedText ( XMP_StringPtr  schemaNS,
-							XMP_StringPtr  arrayName,
-							XMP_StringPtr  _genericLang,
-							XMP_StringPtr  _specificLang,
-							XMP_StringPtr  itemValue,
-							XMP_OptionBits options )
-{
-	UNUSED(options);	// Avoid unused parameter warning.
-
-	XMP_Assert ( (schemaNS != 0) && (arrayName != 0) && (_genericLang != 0) && (_specificLang != 0) );	// Enforced by wrapper.
-
-	XMP_VarString zGenericLang  ( _genericLang );
-	XMP_VarString zSpecificLang ( _specificLang );
-	NormalizeLangValue ( &zGenericLang );
-	NormalizeLangValue ( &zSpecificLang );
-	
-	XMP_StringPtr genericLang  = zGenericLang.c_str();
-	XMP_StringPtr specificLang = zSpecificLang.c_str();
-	
-	XMP_ExpandedXPath arrayPath;
-	ExpandXPath ( schemaNS, arrayName, &arrayPath );
-	
-	// Find the array node and set the options if it was just created.
-	XMP_Node * arrayNode = FindNode ( &tree, arrayPath, kXMP_CreateNodes,
-									  (kXMP_PropValueIsArray | kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate) );
-	if ( arrayNode == 0 ) XMP_Throw ( "Failed to find or create array node", kXMPErr_BadXPath );
-	if ( ! XMP_ArrayIsAltText(arrayNode->options) ) {
-		if ( arrayNode->children.empty() && XMP_ArrayIsAlternate(arrayNode->options) ) {
-			arrayNode->options |= kXMP_PropArrayIsAltText;
-		} else {
-			XMP_Throw ( "Localized text array is not alt-text", kXMPErr_BadXPath );
-		}
-	}
-	
-	// Make sure the x-default item, if any, is first.
-	
-	size_t itemNum, itemLim;
-	XMP_Node * xdItem = 0;
-	bool haveXDefault = false;
-	
-	for ( itemNum = 0, itemLim = arrayNode->children.size(); itemNum < itemLim; ++itemNum ) {
-		XMP_Node * currItem = arrayNode->children[itemNum];
-		XMP_Assert ( XMP_PropHasLang(currItem->options) );
-		if ( currItem->qualifiers.empty() || (currItem->qualifiers[0]->name != "xml:lang") ) {
-			XMP_Throw ( "Language qualifier must be first", kXMPErr_BadXPath );
-		}
-		if ( currItem->qualifiers[0]->value == "x-default" ) {
-			xdItem = currItem;
-			haveXDefault = true;
-			break;
-		}
-	}
-	
-	if ( haveXDefault && (itemNum != 0) ) {
-		XMP_Assert ( arrayNode->children[itemNum]->qualifiers[0]->value == "x-default" );
-		XMP_Node * temp = arrayNode->children[0];
-		arrayNode->children[0] = arrayNode->children[itemNum];
-		arrayNode->children[itemNum] = temp;
-	}
-	
-	// Find the appropriate item. ChooseLocalizedText will make sure the array is a language alternative.
-		
-	const XMP_Node * cItemNode;	// ! ChooseLocalizedText returns a pointer to a const node.
-	XMP_CLTMatch match = ChooseLocalizedText ( arrayNode, genericLang, specificLang, &cItemNode );
-	XMP_Node * itemNode = const_cast<XMP_Node*> ( cItemNode );
-
-	const bool specificXDefault = XMP_LitMatch ( specificLang, "x-default" );
-	
-	switch ( match ) {
-
-		case kXMP_CLT_NoValues :
-
-			// Create the array items for the specificLang and x-default, with x-default first.
-			AppendLangItem ( arrayNode, "x-default", itemValue );
-			haveXDefault = true;
-			if ( ! specificXDefault ) AppendLangItem ( arrayNode, specificLang, itemValue );
-			break;
-			
-		case kXMP_CLT_SpecificMatch :
-		
-			if ( ! specificXDefault ) {
-				// Update the specific item, update x-default if it matches the old value.
-				if ( haveXDefault && (xdItem != itemNode) && (xdItem->value == itemNode->value) ) {
-					SetNodeValue ( xdItem, itemValue );
-				}
-				SetNodeValue ( itemNode, itemValue );	// ! Do this after the x-default check!
-			} else {
-				// Update all items whose values match the old x-default value.
-				XMP_Assert ( haveXDefault && (xdItem == itemNode) );
-				for ( itemNum = 0, itemLim = arrayNode->children.size(); itemNum < itemLim; ++itemNum ) {
-					XMP_Node * currItem = arrayNode->children[itemNum];
-					if ( (currItem == xdItem) || (currItem->value != xdItem->value) ) continue;
-					SetNodeValue ( currItem, itemValue );
-				}
-				SetNodeValue ( xdItem, itemValue );	// And finally do the x-default item.
-			}
-			break;
-
-		case kXMP_CLT_SingleGeneric :
-		
-			// Update the generic item, update x-default if it matches the old value.
-			if ( haveXDefault && (xdItem != itemNode) && (xdItem->value == itemNode->value) ) {
-				SetNodeValue ( xdItem, itemValue );
-			}
-			SetNodeValue ( itemNode, itemValue );	// ! Do this after the x-default check!
-			break;
-
-		case kXMP_CLT_MultipleGeneric :
-		
-			// Create the specific language, ignore x-default.
-			AppendLangItem ( arrayNode, specificLang, itemValue );
-			if ( specificXDefault ) haveXDefault = true;
-			break;
-			
-		case kXMP_CLT_XDefault :
-
-			// Create the specific language, update x-default if it was the only item.
-			if ( arrayNode->children.size() == 1 ) SetNodeValue ( xdItem, itemValue );
-			AppendLangItem ( arrayNode, specificLang, itemValue );
-			break;
-
-		case kXMP_CLT_FirstItem	:
-
-			// Create the specific language, don't add an x-default item.
-			AppendLangItem ( arrayNode, specificLang, itemValue );
-			if ( specificXDefault ) haveXDefault = true;
-			break;
-			
-		default :
-			XMP_Throw ( "Unexpected result from ChooseLocalizedText", kXMPErr_InternalFailure );
-
-	}
-
-	// Add an x-default at the front if needed.
-	if ( (! haveXDefault) && (arrayNode->children.size() == 1) ) {
-		AppendLangItem ( arrayNode, "x-default", itemValue );
-	}
-
-}	// SetLocalizedText
-
-
-// -------------------------------------------------------------------------------------------------
-// GetProperty_Bool
-// ----------------
-
-bool
-XMPMeta::GetProperty_Bool ( XMP_StringPtr	 schemaNS,
-							XMP_StringPtr	 propName,
-							bool *			 propValue,
-							XMP_OptionBits * options ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (propValue != 0) && (options != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	valueStr;
-	XMP_StringLen	valueLen;
-	
-	bool found = GetProperty ( schemaNS, propName, &valueStr, &valueLen, options );
-	if ( found ) {
-		if ( ! XMP_PropIsSimple ( *options ) ) XMP_Throw ( "Property must be simple", kXMPErr_BadXPath );
-		*propValue = XMPUtils::ConvertToBool ( valueStr );
-	}
-	return found;
-	
-}	// GetProperty_Bool
-
-
-// -------------------------------------------------------------------------------------------------
-// GetProperty_Int
-// ---------------
-
-bool
-XMPMeta::GetProperty_Int ( XMP_StringPtr	schemaNS,
-						   XMP_StringPtr	propName,
-						   XMP_Int32 *		propValue,
-						   XMP_OptionBits *	options ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (propValue != 0) && (options != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	valueStr;
-	XMP_StringLen	valueLen;
-	
-	bool found = GetProperty ( schemaNS, propName, &valueStr, &valueLen, options );
-	if ( found ) {
-		if ( ! XMP_PropIsSimple ( *options ) ) XMP_Throw ( "Property must be simple", kXMPErr_BadXPath );
-		*propValue = XMPUtils::ConvertToInt ( valueStr );
-	}
-	return found;
-	
-}	// GetProperty_Int
-
-
-// -------------------------------------------------------------------------------------------------
-// GetProperty_Int64
-// -----------------
-
-bool
-XMPMeta::GetProperty_Int64 ( XMP_StringPtr	  schemaNS,
-						     XMP_StringPtr	  propName,
-						     XMP_Int64 *	  propValue,
-						     XMP_OptionBits * options ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (propValue != 0) && (options != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	valueStr;
-	XMP_StringLen	valueLen;
-	
-	bool found = GetProperty ( schemaNS, propName, &valueStr, &valueLen, options );
-	if ( found ) {
-		if ( ! XMP_PropIsSimple ( *options ) ) XMP_Throw ( "Property must be simple", kXMPErr_BadXPath );
-		*propValue = XMPUtils::ConvertToInt64 ( valueStr );
-	}
-	return found;
-	
-}	// GetProperty_Int64
-
-
-// -------------------------------------------------------------------------------------------------
-// GetProperty_Float
-// -----------------
-
-bool
-XMPMeta::GetProperty_Float ( XMP_StringPtr	  schemaNS,
-							 XMP_StringPtr	  propName,
-							 double *		  propValue,
-							 XMP_OptionBits * options ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (propValue != 0) && (options != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	valueStr;
-	XMP_StringLen	valueLen;
-	
-	bool found = GetProperty ( schemaNS, propName, &valueStr, &valueLen, options );
-	if ( found ) {
-		if ( ! XMP_PropIsSimple ( *options ) ) XMP_Throw ( "Property must be simple", kXMPErr_BadXPath );
-		*propValue = XMPUtils::ConvertToFloat ( valueStr );
-	}
-	return found;
-	
-}	// GetProperty_Float
-
-
-// -------------------------------------------------------------------------------------------------
-// GetProperty_Date
-// ----------------
-
-bool
-XMPMeta::GetProperty_Date ( XMP_StringPtr	 schemaNS,
-							XMP_StringPtr	 propName,
-							XMP_DateTime *	 propValue,
-							XMP_OptionBits * options ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (propValue != 0) && (options != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	valueStr;
-	XMP_StringLen	valueLen;
-	
-	bool found = GetProperty ( schemaNS, propName, &valueStr, &valueLen, options );
-	if ( found )  {
-		if ( ! XMP_PropIsSimple ( *options ) ) XMP_Throw ( "Property must be simple", kXMPErr_BadXPath );
-		XMPUtils::ConvertToDate ( valueStr, propValue );
-	}
-	return found;
-	
-}	// GetProperty_Date
-
-
-// -------------------------------------------------------------------------------------------------
-// SetProperty_Bool
-// ----------------
-
-void
-XMPMeta::SetProperty_Bool ( XMP_StringPtr  schemaNS,
-							XMP_StringPtr  propName,
-							bool		   propValue,
-							XMP_OptionBits options )
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	valueStr;
-	XMP_StringLen	valueLen;
-	
-	XMPUtils::ConvertFromBool ( propValue, &valueStr, &valueLen );
-	SetProperty ( schemaNS, propName, valueStr, options );
-	
-}	// SetProperty_Bool
-
-
-// -------------------------------------------------------------------------------------------------
-// SetProperty_Int
-// ---------------
-
-void
-XMPMeta::SetProperty_Int ( XMP_StringPtr  schemaNS,
-						   XMP_StringPtr  propName,
-						   XMP_Int32	  propValue,
-						   XMP_OptionBits options )
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	valueStr;
-	XMP_StringLen	valueLen;
-	
-	XMPUtils::ConvertFromInt ( propValue, "", &valueStr, &valueLen );
-	SetProperty ( schemaNS, propName, valueStr, options );
-	
-}	// SetProperty_Int
-
-
-// -------------------------------------------------------------------------------------------------
-// SetProperty_Int64
-// -----------------
-
-void
-XMPMeta::SetProperty_Int64 ( XMP_StringPtr  schemaNS,
-						     XMP_StringPtr  propName,
-						     XMP_Int64	    propValue,
-						     XMP_OptionBits options )
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	valueStr;
-	XMP_StringLen	valueLen;
-	
-	XMPUtils::ConvertFromInt64 ( propValue, "", &valueStr, &valueLen );
-	SetProperty ( schemaNS, propName, valueStr, options );
-	
-}	// SetProperty_Int64
-
-
-// -------------------------------------------------------------------------------------------------
-// SetProperty_Float
-// -----------------
-
-void
-XMPMeta::SetProperty_Float ( XMP_StringPtr	schemaNS,
-							 XMP_StringPtr	propName,
-							 double			propValue,
-							 XMP_OptionBits	options )
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	valueStr;
-	XMP_StringLen	valueLen;
-	
-	XMPUtils::ConvertFromFloat ( propValue, "", &valueStr, &valueLen );
-	SetProperty ( schemaNS, propName, valueStr, options );
-	
-}	// SetProperty_Float
-
-
-// -------------------------------------------------------------------------------------------------
-// SetProperty_Date
-// ----------------
-
-void
-XMPMeta::SetProperty_Date ( XMP_StringPtr		   schemaNS,
-							XMP_StringPtr		   propName,
-							const	XMP_DateTime & propValue,
-							XMP_OptionBits		   options )
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// Enforced by wrapper.
-
-	XMP_StringPtr	valueStr;
-	XMP_StringLen	valueLen;
-	
-	XMPUtils::ConvertFromDate ( propValue, &valueStr, &valueLen );
-	SetProperty ( schemaNS, propName, valueStr, options );
-	
-}	// SetProperty_Date
-
-// =================================================================================================
-
diff --git a/xmpsdk/src/XMPMeta-Parse.cpp b/xmpsdk/src/XMPMeta-Parse.cpp
deleted file mode 100644
index 9f66fe8e..00000000
--- a/xmpsdk/src/XMPMeta-Parse.cpp
+++ /dev/null
@@ -1,1291 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-//
-// Adobe patent application tracking #P435, entitled 'Unique markers to simplify embedding data of
-// one format in a file with a different format', inventors: Sean Parent, Greg Gilley.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-
-#include "XMPMeta.hpp"
-#include "XMPUtils.hpp"
-
-#include "UnicodeInlines.incl_cpp"
-#include "UnicodeConversions.hpp"
-#include "ExpatAdapter.hpp"
-
-#if XMP_DebugBuild
-	#include <iostream>
-#endif
-
-using namespace std;
-
-#if XMP_WinBuild
-#ifdef _MSC_VER
-	#pragma warning ( disable : 4533 )	// initialization of '...' is skipped by 'goto ...'
-	#pragma warning ( disable : 4702 )	// unreachable code
-	#pragma warning ( disable : 4800 )	// forcing value to bool 'true' or 'false' (performance warning)
-	#pragma warning ( disable : 4996 )	// '...' was declared deprecated
-#endif
-#endif
-
-
-// *** Use the XMP_PropIsXyz (Schema, Simple, Struct, Array, ...) macros
-// *** Add debug codegen checks, e.g. that typical masking operations really work
-// *** Change all uses of strcmp and strncmp to XMP_LitMatch and XMP_LitNMatch
-
-
-// =================================================================================================
-// Local Types and Constants
-// =========================
-
-
-// =================================================================================================
-// Static Variables
-// ================
-
-#ifndef Trace_ParsingHackery
-	#define Trace_ParsingHackery 0
-#endif
-
-static const char * kReplaceLatin1[128] =
-	{
-
-		// The 0x80..0x9F range is undefined in Latin-1, but is defined in Windows code page 1252.
-		// The bytes 0x81, 0x8D, 0x8F, 0x90, and 0x9D are formally undefined by Windows 1252, but
-		// their conversion API maps them to U+0081, etc. These are in XML's RestrictedChar set, so
-		// we map them to a space.
-		
-		"\xE2\x82\xAC", " ",            "\xE2\x80\x9A", "\xC6\x92",		// 0x80 .. 0x83
-		"\xE2\x80\x9E", "\xE2\x80\xA6", "\xE2\x80\xA0", "\xE2\x80\xA1",	// 0x84 .. 0x87
-		"\xCB\x86",     "\xE2\x80\xB0", "\xC5\xA0",     "\xE2\x80\xB9",	// 0x88 .. 0x8B
-		"\xC5\x92",     " ",            "\xC5\xBD",     " ",			// 0x8C .. 0x8F
-
-		" ",            "\xE2\x80\x98", "\xE2\x80\x99", "\xE2\x80\x9C",	// 0x90 .. 0x93
-		"\xE2\x80\x9D", "\xE2\x80\xA2", "\xE2\x80\x93", "\xE2\x80\x94",	// 0x94 .. 0x97
-		"\xCB\x9C",     "\xE2\x84\xA2", "\xC5\xA1",     "\xE2\x80\xBA",	// 0x98 .. 0x9B
-		"\xC5\x93",     " ",            "\xC5\xBE",     "\xC5\xB8",		// 0x9C .. 0x9F
-
-		// These are the UTF-8 forms of the official Latin-1 characters in the range 0xA0..0xFF. Not
-		// too surprisingly these map to U+00A0, etc. Which is the Unicode Latin Supplement range.
-		
-		"\xC2\xA0", "\xC2\xA1", "\xC2\xA2", "\xC2\xA3", "\xC2\xA4", "\xC2\xA5", "\xC2\xA6", "\xC2\xA7",	// 0xA0 .. 0xA7
-		"\xC2\xA8", "\xC2\xA9", "\xC2\xAA", "\xC2\xAB", "\xC2\xAC", "\xC2\xAD", "\xC2\xAE", "\xC2\xAF",	// 0xA8 .. 0xAF
-
-		"\xC2\xB0", "\xC2\xB1", "\xC2\xB2", "\xC2\xB3", "\xC2\xB4", "\xC2\xB5", "\xC2\xB6", "\xC2\xB7",	// 0xB0 .. 0xB7
-		"\xC2\xB8", "\xC2\xB9", "\xC2\xBA", "\xC2\xBB", "\xC2\xBC", "\xC2\xBD", "\xC2\xBE", "\xC2\xBF",	// 0xB8 .. 0xBF
-
-		"\xC3\x80", "\xC3\x81", "\xC3\x82", "\xC3\x83", "\xC3\x84", "\xC3\x85", "\xC3\x86", "\xC3\x87",	// 0xC0 .. 0xC7
-		"\xC3\x88", "\xC3\x89", "\xC3\x8A", "\xC3\x8B", "\xC3\x8C", "\xC3\x8D", "\xC3\x8E", "\xC3\x8F",	// 0xC8 .. 0xCF
-
-		"\xC3\x90", "\xC3\x91", "\xC3\x92", "\xC3\x93", "\xC3\x94", "\xC3\x95", "\xC3\x96", "\xC3\x97",	// 0xD0 .. 0xD7
-		"\xC3\x98", "\xC3\x99", "\xC3\x9A", "\xC3\x9B", "\xC3\x9C", "\xC3\x9D", "\xC3\x9E", "\xC3\x9F",	// 0xD8 .. 0xDF
-
-		"\xC3\xA0", "\xC3\xA1", "\xC3\xA2", "\xC3\xA3", "\xC3\xA4", "\xC3\xA5", "\xC3\xA6", "\xC3\xA7",	// 0xE0 .. 0xE7
-		"\xC3\xA8", "\xC3\xA9", "\xC3\xAA", "\xC3\xAB", "\xC3\xAC", "\xC3\xAD", "\xC3\xAE", "\xC3\xAF",	// 0xE8 .. 0xEF
-
-		"\xC3\xB0", "\xC3\xB1", "\xC3\xB2", "\xC3\xB3", "\xC3\xB4", "\xC3\xB5", "\xC3\xB6", "\xC3\xB7",	// 0xF0 .. 0xF7
-		"\xC3\xB8", "\xC3\xB9", "\xC3\xBA", "\xC3\xBB", "\xC3\xBC", "\xC3\xBD", "\xC3\xBE", "\xC3\xBF",	// 0xF8 .. 0xFF
-
-	};
-
-
-// =================================================================================================
-// Local Utilities
-// ===============
-
-
-#define IsHexDigit(ch)		( (('0' <= (ch)) && ((ch) <= '9')) || (('A' <= (ch)) && ((ch) <= 'F')) )
-#define HexDigitValue(ch)	( (((ch) - '0') < 10) ? ((ch) - '0') : ((ch) - 'A' + 10) )
-
-
-// -------------------------------------------------------------------------------------------------
-// PickBestRoot
-// ------------
-static const XML_Node * PickBestRoot ( const XML_Node & xmlParent, XMP_OptionBits options )
-{
-
-	// Look among this parent's content for x:xmpmeta. The recursion for x:xmpmeta is broader than
-	// the strictly defined choice, but gives us smaller code.
-	for ( size_t childNum = 0, childLim = xmlParent.content.size(); childNum < childLim; ++childNum ) {
-		const XML_Node * childNode = xmlParent.content[childNum];
-		if ( childNode->kind != kElemNode ) continue;
-		if ( (childNode->name == "x:xmpmeta") || (childNode->name == "x:xapmeta") ) return PickBestRoot ( *childNode, 0 );
-	}
-	// Look among this parent's content for a bare rdf:RDF if that is allowed.
-	if ( ! (options & kXMP_RequireXMPMeta) ) {
-		for ( size_t childNum = 0, childLim = xmlParent.content.size(); childNum < childLim; ++childNum ) {
-			const XML_Node * childNode = xmlParent.content[childNum];
-			if ( childNode->kind != kElemNode ) continue;
-			if ( childNode->name == "rdf:RDF" ) return childNode;
-		}
-	}
-	
-	// Recurse into the content.
-	for ( size_t childNum = 0, childLim = xmlParent.content.size(); childNum < childLim; ++childNum ) {
-		const XML_Node * foundRoot = PickBestRoot ( *xmlParent.content[childNum], options );
-		if ( foundRoot != 0 ) return foundRoot;
-	}
-	
-	return 0;
-
-}	// PickBestRoot
-
-// -------------------------------------------------------------------------------------------------
-// FindRootNode
-// ------------
-//
-// Find the XML node that is the root of the XMP data tree. Generally this will be an outer node,
-// but it could be anywhere if a general XML document is parsed (e.g. SVG). The XML parser counted
-// all possible root nodes, and kept a pointer to the last one. If there is more than one possible
-// root use PickBestRoot to choose among them.
-//
-// If there is a root node, try to extract the version of the previous XMP toolkit.
-
-static const XML_Node * FindRootNode ( XMPMeta * thiz, const XMLParserAdapter & xmlParser, XMP_OptionBits options )
-{
-	const XML_Node * rootNode = xmlParser.rootNode;
-	
-	if ( xmlParser.rootCount > 1 ) rootNode = PickBestRoot ( xmlParser.tree, options );
-	if ( rootNode == 0 ) return 0;
-	
-	// We have a root node. Try to extract previous toolkit version number.
-	
-	XMP_StringPtr verStr = "";
-	
-		XMP_Assert ( rootNode->name == "rdf:RDF" );
-	
-		if ( (options & kXMP_RequireXMPMeta) &&
-		     ((rootNode->parent == 0) ||
-		      ((rootNode->parent->name != "x:xmpmeta") && (rootNode->parent->name != "x:xapmeta"))) ) return 0;
-
-		for ( size_t attrNum = 0, attrLim = rootNode->parent->attrs.size(); attrNum < attrLim; ++attrNum ) {
-			const XML_Node * currAttr =rootNode->parent->attrs[attrNum];
-			if ( (currAttr->name == "x:xmptk") || (currAttr->name == "x:xaptk") ) {
-				verStr = currAttr->value.c_str();
-				break;
-			}
-		}
-		
-	// Decode the version number into MMmmuubbb digits. If any part is too big, peg it at 99 or 999.
-	
-	unsigned long part;
-	while ( (*verStr != 0) && ((*verStr < '0') || (*verStr > '9')) ) ++verStr;
-	
-	part = 0;
-	while ( (*verStr != 0) && ('0' <= *verStr) && (*verStr <= '9') ) {
-		part = (part * 10) + (*verStr - '0');
-		++verStr;
-	}
-	if ( part > 99 ) part = 99;
-	thiz->prevTkVer = part * 100*100*1000;
-	
-	part = 0;
-	if ( *verStr == '.' ) ++verStr;
-	while ( (*verStr != 0) && ('0' <= *verStr) && (*verStr <= '9') ) {
-		part = (part * 10) + (*verStr - '0');
-		++verStr;
-	}
-	if ( part > 99 ) part = 99;
-	thiz->prevTkVer += part * 100*1000;
-	
-	part = 0;
-	if ( *verStr == '.' ) ++verStr;
-	while ( (*verStr != 0) && ('0' <= *verStr) && (*verStr <= '9') ) {
-		part = (part * 10) + (*verStr - '0');
-		++verStr;
-	}
-	if ( part > 99 ) part = 99;
-	thiz->prevTkVer += part * 1000;
-	
-	part = 0;
-	if ( *verStr == '-' ) ++verStr;
-	while ( (*verStr != 0) && ('0' <= *verStr) && (*verStr <= '9') ) {
-		part = (part * 10) + (*verStr - '0');
-		++verStr;
-	}
-	if ( part > 999 ) part = 999;
-	thiz->prevTkVer += part;
-	
-	return rootNode;
-	
-}	// FindRootNode
-
-// -------------------------------------------------------------------------------------------------
-// NormalizeDCArrays
-// -----------------
-//
-// Undo the denormalization performed by the XMP used in Acrobat 5. If a Dublin Core array had only
-// one item, it was serialized as a simple property. The xml:lang attribute was dropped from an
-// alt-text item if the language was x-default.
-
-// *** This depends on the dc: namespace prefix.
-
-static void
-NormalizeDCArrays ( XMP_Node * xmpTree )
-{
-	XMP_Node * dcSchema = FindSchemaNode ( xmpTree, kXMP_NS_DC, kXMP_ExistingOnly );
-	if ( dcSchema == 0 ) return;
-	
-	for ( size_t propNum = 0, propLimit = dcSchema->children.size(); propNum < propLimit; ++propNum ) {
-		XMP_Node *     currProp  = dcSchema->children[propNum];
-		XMP_OptionBits arrayForm = 0;
-		
-		if ( ! XMP_PropIsSimple ( currProp->options ) ) continue;	// Nothing to do if not simple.
-		
-		if ( (currProp->name == "dc:creator" )     ||	// See if it is supposed to be an array.
-		     (currProp->name == "dc:date" ) ) {			// *** Think about an array of char* and a loop.
-			arrayForm = kXMP_PropArrayIsOrdered;
-		} else if (
-		     (currProp->name == "dc:description" ) ||
-		     (currProp->name == "dc:rights" )      ||
-		     (currProp->name == "dc:title" ) ) {
-			arrayForm = kXMP_PropArrayIsAltText;
-		} else if (
-		     (currProp->name == "dc:contributor" ) ||
-		     (currProp->name == "dc:language" )    ||
-		     (currProp->name == "dc:publisher" )   ||
-		     (currProp->name == "dc:relation" )    ||
-		     (currProp->name == "dc:subject" )     ||
-		     (currProp->name == "dc:type" ) ) {
-			arrayForm = kXMP_PropValueIsArray;
-		}
-		if ( arrayForm == 0 ) continue;	// Nothing to do if it isn't supposed to be an array.
-		
-		arrayForm = VerifySetOptions ( arrayForm, 0 );	// Set the implicit array bits.
-		XMP_Node * newArray = new XMP_Node ( dcSchema, currProp->name.c_str(), arrayForm );
-		dcSchema->children[propNum] = newArray;
-		newArray->children.push_back ( currProp );
-		currProp->parent = newArray;
-		currProp->name = kXMP_ArrayItemName;
-		
-		if ( XMP_ArrayIsAltText ( arrayForm ) && (! (currProp->options & kXMP_PropHasLang)) ) {
-			XMP_Node * newLang = new XMP_Node ( currProp, "xml:lang", "x-default", kXMP_PropIsQualifier );
-			currProp->options |= (kXMP_PropHasQualifiers | kXMP_PropHasLang);
-			if ( currProp->qualifiers.empty() ) {	// *** Need a util?
-				currProp->qualifiers.push_back ( newLang );
-			} else {
-				currProp->qualifiers.insert ( currProp->qualifiers.begin(), newLang );
-			}
-		}
-
-	}
-	
-}	// NormalizeDCArrays
-
-
-// -------------------------------------------------------------------------------------------------
-// CompareAliasedSubtrees
-// ----------------------
-
-// *** Change to do some alias-specific setup, then use CompareSubtrees. One special case for
-// *** aliases is a simple to x-default alias, the options and qualifiers obviously differ.
-
-static void
-CompareAliasedSubtrees ( XMP_Node * aliasNode, XMP_Node * baseNode, bool outerCall = true )
-{
-	// ! The outermost call is special. The names almost certainly differ. The qualifiers (and
-	// ! hence options) will differ for an alias to the x-default item of a langAlt array.
-	if ( (aliasNode->value != baseNode->value) ||
-	     (aliasNode->children.size() != baseNode->children.size()) ) {
-		XMP_Throw ( "Mismatch between alias and base nodes", kXMPErr_BadXMP );
-	}
-	if ( ! outerCall ) {
-		if ( (aliasNode->name != baseNode->name) ||
-		     (aliasNode->options != baseNode->options) ||
-		     (aliasNode->qualifiers.size() != baseNode->qualifiers.size()) ) {
-			XMP_Throw ( "Mismatch between alias and base nodes", kXMPErr_BadXMP );
-		}
-	}
-	
-	for ( size_t childNum = 0, childLim = aliasNode->children.size(); childNum < childLim; ++childNum ) {
-		XMP_Node * aliasChild = aliasNode->children[childNum];
-		XMP_Node * baseChild  = baseNode->children[childNum];
-		CompareAliasedSubtrees ( aliasChild, baseChild, false );
-	}
-	
-	for ( size_t qualNum = 0, qualLim = aliasNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
-		XMP_Node * aliasQual = aliasNode->qualifiers[qualNum];
-		XMP_Node * baseQual  = baseNode->qualifiers[qualNum];
-		CompareAliasedSubtrees ( aliasQual, baseQual, false );
-	}
-	
-}	// CompareAliasedSubtrees
-
-
-// -------------------------------------------------------------------------------------------------
-// TransplantArrayItemAlias
-// ------------------------
-
-static void
-TransplantArrayItemAlias ( XMP_Node * oldParent, size_t oldNum, XMP_Node * newParent )
-{
-	XMP_Node * childNode = oldParent->children[oldNum];
-
-	if ( newParent->options & kXMP_PropArrayIsAltText ) {
-		if ( childNode->options & kXMP_PropHasLang ) {
-			XMP_Throw ( "Alias to x-default already has a language qualifier", kXMPErr_BadXMP );	// *** Allow x-default.
-		}
-		childNode->options |= (kXMP_PropHasQualifiers | kXMP_PropHasLang);
-		XMP_Node * langQual = new XMP_Node ( childNode, "xml:lang", "x-default", kXMP_PropIsQualifier );	// *** AddLangQual util?
-		if ( childNode->qualifiers.empty() ) {
-			childNode->qualifiers.push_back ( langQual );
-		} else {
-			childNode->qualifiers.insert ( childNode->qualifiers.begin(), langQual );
-		}
-	}
-
-	oldParent->children.erase ( oldParent->children.begin() + oldNum );
-	childNode->name = kXMP_ArrayItemName;
-	childNode->parent = newParent;
-	if ( newParent->children.empty() ) {
-		newParent->children.push_back ( childNode );
-	} else {
-		newParent->children.insert ( newParent->children.begin(), childNode );
-	}
-
-}	// TransplantArrayItemAlias
-
-
-// -------------------------------------------------------------------------------------------------
-// TransplantNamedAlias
-// --------------------
-
-static void
-TransplantNamedAlias ( XMP_Node * oldParent, size_t oldNum, XMP_Node * newParent, XMP_VarString & newName )
-{
-	XMP_Node * childNode = oldParent->children[oldNum];
-
-	oldParent->children.erase ( oldParent->children.begin() + oldNum );
-	childNode->name = newName;
-	childNode->parent = newParent;
-	newParent->children.push_back ( childNode );
-
-}	// TransplantNamedAlias
-
-
-// -------------------------------------------------------------------------------------------------
-// MoveExplicitAliases
-// -------------------
-
-static void
-MoveExplicitAliases ( XMP_Node * tree, XMP_OptionBits parseOptions )
-{
-	tree->options ^= kXMP_PropHasAliases;
-	const bool strictAliasing = ((parseOptions & kXMP_StrictAliasing) != 0);
-	
-	// Visit all of the top level nodes looking for aliases. If there is no base, transplant the
-	// alias subtree. If there is a base and strict aliasing is on, make sure the alias and base 
-	// subtrees match.
-	
-	// ! Use "while" loops not "for" loops since both the schema and property loops can remove the
-	// ! current item from the vector being traversed. And don't increment the counter for a delete.
-	
-	size_t schemaNum = 0;
-	while ( schemaNum < tree->children.size() ) {
-		XMP_Node * currSchema = tree->children[schemaNum];
-		
-		size_t propNum = 0;
-		while ( propNum < currSchema->children.size() ) {
-			XMP_Node * currProp = currSchema->children[propNum];
-			if ( ! (currProp->options & kXMP_PropIsAlias) ) {
-				++propNum;
-				continue;
-			}
-			currProp->options ^= kXMP_PropIsAlias;
-
-			// Find the base path, look for the base schema and root node.
-
-			XMP_AliasMapPos aliasPos = sRegisteredAliasMap->find ( currProp->name );
-			XMP_Assert ( aliasPos != sRegisteredAliasMap->end() );
-			XMP_ExpandedXPath & basePath = aliasPos->second;
-			XMP_OptionBits arrayOptions = (basePath[kRootPropStep].options & kXMP_PropArrayFormMask);
-
-			XMP_Node * baseSchema = FindSchemaNode ( tree, basePath[kSchemaStep].step.c_str(), kXMP_CreateNodes );
-			if ( baseSchema->options & kXMP_NewImplicitNode ) baseSchema->options ^= kXMP_NewImplicitNode;
-			XMP_Node * baseNode = FindChildNode ( baseSchema, basePath[kRootPropStep].step.c_str(), kXMP_ExistingOnly );
-
-			if ( baseNode == 0 ) {
-			
-				if ( basePath.size() == 2 ) {
-					// A top-to-top alias, transplant the property.
-					TransplantNamedAlias ( currSchema, propNum, baseSchema, basePath[kRootPropStep].step );
-				} else {
-					// An alias to an array item, create the array and transplant the property.
-					baseNode = new XMP_Node ( baseSchema, basePath[kRootPropStep].step.c_str(), arrayOptions );
-					baseSchema->children.push_back ( baseNode );
-					TransplantArrayItemAlias ( currSchema, propNum, baseNode );
-				}
-			
-			} else if ( basePath.size() == 2 ) {
-			
-				// The base node does exist and this is a top-to-top alias. Check for conflicts if
-				// strict aliasing is on. Remove and delete the alias subtree.
-				if ( strictAliasing ) CompareAliasedSubtrees ( currProp, baseNode );
-				currSchema->children.erase ( currSchema->children.begin() + propNum );
-				delete currProp;
-			
-			} else {
-			
-				// This is an alias to an array item and the array exists. Look for the aliased item.
-				// Then transplant or check & delete as appropriate.
-				
-				XMP_Node * itemNode = 0;
-				if ( arrayOptions & kXMP_PropArrayIsAltText ) {
-					XMP_Index xdIndex = LookupLangItem ( baseNode, *xdefaultName );
-					if ( xdIndex != -1 ) itemNode = baseNode->children[xdIndex];
-				} else if ( ! baseNode->children.empty() ) {
-					itemNode = baseNode->children[0];
-				}
-				
-				if ( itemNode == 0 ) {
-					TransplantArrayItemAlias ( currSchema, propNum, baseNode );
-				} else {
-					if ( strictAliasing ) CompareAliasedSubtrees ( currProp, itemNode );
-					currSchema->children.erase ( currSchema->children.begin() + propNum );
-					delete currProp;
-				}
-
-			}
-
-		}	// Property loop
-		
-		// Increment the counter or remove an empty schema node.
-		if ( currSchema->children.size() > 0 ) {
-			++schemaNum;
-		} else {
-			delete tree->children[schemaNum];	// ! Delete the schema node itself.
-			tree->children.erase ( tree->children.begin() + schemaNum );
-		}
-		
-	}	// Schema loop
-	
-}	// MoveExplicitAliases
-
-
-// -------------------------------------------------------------------------------------------------
-// FixGPSTimeStamp
-// ---------------
-
-static void
-FixGPSTimeStamp ( XMP_Node * exifSchema, XMP_Node * gpsDateTime )
-{
-	XMP_DateTime binGPSStamp;
-	try {
-		XMPUtils::ConvertToDate ( gpsDateTime->value.c_str(), &binGPSStamp );
-	} catch ( ... ) {
-		return;	// Don't let a bad date stop other things.
-	}
-	if ( (binGPSStamp.year != 0) || (binGPSStamp.month != 0) || (binGPSStamp.day != 0) ) return;
-	
-	XMP_Node * otherDate = FindChildNode ( exifSchema, "exif:DateTimeOriginal", kXMP_ExistingOnly );
-	if ( otherDate == 0 ) otherDate = FindChildNode ( exifSchema, "exif:DateTimeDigitized", kXMP_ExistingOnly );
-	if ( otherDate == 0 ) return;
-
-	XMP_DateTime binOtherDate;
-	try {
-		XMPUtils::ConvertToDate ( otherDate->value.c_str(), &binOtherDate );
-	} catch ( ... ) {
-		return;	// Don't let a bad date stop other things.
-	}
-	
-	binGPSStamp.year  = binOtherDate.year;
-	binGPSStamp.month = binOtherDate.month;
-	binGPSStamp.day   = binOtherDate.day;
-
-	XMP_StringPtr goodStr;
-	XMP_StringLen goodLen;
-	XMPUtils::ConvertFromDate ( binGPSStamp, &goodStr, &goodLen );
-	
-	gpsDateTime->value.assign ( goodStr, goodLen );
-
-}	// FixGPSTimeStamp
-
-
-// -------------------------------------------------------------------------------------------------
-// MigrateAudioCopyright
-// ---------------------
-//
-// The initial support for WAV files mapped a legacy ID3 audio copyright into a new xmpDM:copyright
-// property. This is special case code to migrate that into dc:rights['x-default']. The rules:
-//
-//   1. If there is no dc:rights array, or an empty array -
-//      Create one with dc:rights['x-default'] set from double linefeed and xmpDM:copyright.
-//
-//   2. If there is a dc:rights array but it has no x-default item -
-//      Create an x-default item as a copy of the first item then apply rule #3.
-//
-//   3. If there is a dc:rights array with an x-default item, look for a double linefeed in the value.
-//      A. If no double linefeed, compare the x-default value to the xmpDM:copyright value.
-//         A1. If they match then leave the x-default value alone.
-//         A2. Otherwise, append a double linefeed and the xmpDM:copyright value to the x-default value.
-//      B. If there is a double linefeed, compare the trailing text to the xmpDM:copyright value.
-//         B1. If they match then leave the x-default value alone.
-//         B2. Otherwise, replace the trailing x-default text with the xmpDM:copyright value.
-//
-//   4. In all cases, delete the xmpDM:copyright property.
-
-static void
-MigrateAudioCopyright ( XMPMeta * xmp, XMP_Node * dmCopyright )
-{
-
-	try {
-	
-		std::string & dmValue = dmCopyright->value;
-		static const char * kDoubleLF = "\xA\xA";
-		
-		XMP_Node * dcSchema = FindSchemaNode ( &xmp->tree, kXMP_NS_DC, kXMP_CreateNodes );
-		XMP_Node * dcRightsArray = FindChildNode ( dcSchema, "dc:rights", kXMP_ExistingOnly );
-		
-		if ( (dcRightsArray == 0) || dcRightsArray->children.empty() ) {
-		
-			// 1. No dc:rights array, create from double linefeed and xmpDM:copyright.
-			dmValue.insert ( 0, kDoubleLF );
-			xmp->SetLocalizedText ( kXMP_NS_DC, "rights", "", "x-default",  dmValue.c_str(), 0 );
-		
-		} else {
-
-			std::string xdefaultStr ( "x-default" );
-			
-			XMP_Index xdIndex = LookupLangItem ( dcRightsArray, xdefaultStr );
-			
-			if ( xdIndex < 0 ) {
-				// 2. No x-default item, create from the first item.
-				XMP_StringPtr firstValue = dcRightsArray->children[0]->value.c_str();
-				xmp->SetLocalizedText ( kXMP_NS_DC, "rights", "", "x-default",  firstValue, 0 );
-				xdIndex = LookupLangItem ( dcRightsArray, xdefaultStr );
-			}
-						
-			// 3. Look for a double linefeed in the x-default value.
-			XMP_Assert ( xdIndex == 0 );
-			std::string & defaultValue = dcRightsArray->children[xdIndex]->value;
-			XMP_Index lfPos = defaultValue.find ( kDoubleLF );
-			
-			if ( lfPos < 0 ) {
-			
-				// 3A. No double LF, compare whole values.
-				if ( dmValue != defaultValue ) {
-					// 3A2. Append the xmpDM:copyright to the x-default item.
-					defaultValue += kDoubleLF;
-					defaultValue += dmValue;
-				}
-			
-			} else {
-			
-				// 3B. Has double LF, compare the tail.
-				if ( defaultValue.compare ( lfPos+2, std::string::npos, dmValue ) != 0 ) {
-					// 3B2. Replace the x-default tail.
-					defaultValue.replace ( lfPos+2, std::string::npos, dmValue );
-				}
-			
-			}
-
-		}
-		
-		// 4. Get rid of the xmpDM:copyright.
-		xmp->DeleteProperty ( kXMP_NS_DM, "copyright" );
-	
-	} catch ( ... ) {
-		// Don't let failures (like a bad dc:rights form) stop other cleanup.
-	}
-
-}	// MigrateAudioCopyright
-
-
-// -------------------------------------------------------------------------------------------------
-// RepairAltText
-// -------------
-//
-// Make sure that the array is well-formed AltText. Each item must be simple and have an xml:lang
-// qualifier. If repairs are needed, keep simple non-empty items by adding the xml:lang.
-
-static void
-RepairAltText ( XMP_Node & tree, XMP_StringPtr schemaNS, XMP_StringPtr arrayName )
-{
-	XMP_Node * schemaNode = FindSchemaNode ( &tree, schemaNS, kXMP_ExistingOnly );
-	if ( schemaNode == 0 ) return;
-	
-	XMP_Node * arrayNode = FindChildNode ( schemaNode, arrayName, kXMP_ExistingOnly );
-	if ( (arrayNode == 0) || XMP_ArrayIsAltText ( arrayNode->options ) ) return;	// Already OK.
-	
-	if ( ! XMP_PropIsArray ( arrayNode->options ) ) return;	// ! Not even an array, leave it alone.
-	// *** Should probably change simple values to LangAlt with 'x-default' item.
-	
-	arrayNode->options |= (kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate | kXMP_PropArrayIsAltText);
-	
-	for ( int i = arrayNode->children.size()-1; i >= 0; --i ) {	// ! Need a signed index type.
-
-		XMP_Node * currChild = arrayNode->children[i];
-
-		if ( ! XMP_PropIsSimple ( currChild->options ) ) {
-
-			// Delete non-simple children.
-			delete ( currChild );
-			arrayNode->children.erase ( arrayNode->children.begin() + i );
-
-		} else if ( ! XMP_PropHasLang ( currChild->options ) ) {
-		
-			if ( currChild->value.empty() ) {
-
-				// Delete empty valued children that have no xml:lang.
-				delete ( currChild );
-				arrayNode->children.erase ( arrayNode->children.begin() + i );
-
-			} else {
-
-				// Add an xml:lang qualifier with the value "x-repair".
-				XMP_Node * repairLang = new XMP_Node ( currChild, "xml:lang", "x-repair", kXMP_PropIsQualifier );
-				if ( currChild->qualifiers.empty() ) {
-					currChild->qualifiers.push_back ( repairLang );
-				} else {
-					currChild->qualifiers.insert ( currChild->qualifiers.begin(), repairLang );
-				}
-				currChild->options |= (kXMP_PropHasQualifiers | kXMP_PropHasLang);
-
-			}
-
-		}
-
-	}
-
-}	// RepairAltText
-
-
-// -------------------------------------------------------------------------------------------------
-// TouchUpDataModel
-// ----------------
-
-static void
-TouchUpDataModel ( XMPMeta * xmp )
-{
-	XMP_Node & tree = xmp->tree;
-	
-	// Do special case touch ups for certain schema.
-
-	XMP_Node * currSchema = 0;
-
-	currSchema = FindSchemaNode ( &tree, kXMP_NS_EXIF, kXMP_ExistingOnly );
-	if ( currSchema != 0 ) {
-
-		// Do a special case fix for exif:GPSTimeStamp.
-		XMP_Node * gpsDateTime = FindChildNode ( currSchema, "exif:GPSTimeStamp", kXMP_ExistingOnly );
-		if ( gpsDateTime != 0 ) FixGPSTimeStamp ( currSchema, gpsDateTime );
-	
-		// *** Should probably have RepairAltText change simple values to LangAlt with 'x-default' item.
-		// *** For now just do this for exif:UserComment, the one case we know about, late in cycle fix.
-		XMP_Node * userComment = FindChildNode ( currSchema, "exif:UserComment", kXMP_ExistingOnly );
-		if ( (userComment != 0) && XMP_PropIsSimple ( userComment->options ) ) {
-			XMP_Node * newChild = new XMP_Node ( userComment, kXMP_ArrayItemName,
-												 userComment->value.c_str(), userComment->options );
-			newChild->qualifiers.swap ( userComment->qualifiers );
-			if ( ! XMP_PropHasLang ( newChild->options ) ) {
-				XMP_Node * langQual = new XMP_Node ( newChild, "xml:lang", "x-default", kXMP_PropIsQualifier );
-				newChild->qualifiers.insert ( newChild->qualifiers.begin(), langQual );
-				newChild->options |= (kXMP_PropHasQualifiers | kXMP_PropHasLang);
-			}
-			userComment->value.erase();
-			userComment->options = kXMP_PropArrayFormMask;	// ! Happens to have all the right bits.
-			userComment->children.push_back ( newChild );
-		}
-
-	}
-
-	currSchema = FindSchemaNode ( &tree, kXMP_NS_DM, kXMP_ExistingOnly );
-	if ( currSchema != 0 ) {
-		// Do a special case migration of xmpDM:copyright to dc:rights['x-default']. Do this before
-		// the dc: touch up since it can affect the dc: schema.
-		XMP_Node * dmCopyright = FindChildNode ( currSchema, "xmpDM:copyright", kXMP_ExistingOnly );
-		if ( dmCopyright != 0 ) MigrateAudioCopyright ( xmp, dmCopyright );
-	}
-
-	currSchema = FindSchemaNode ( &tree, kXMP_NS_DC, kXMP_ExistingOnly );
-	if ( currSchema != 0 ) {
-		// Do a special case fix for dc:subject, make sure it is an unordered array.
-		XMP_Node * dcSubject = FindChildNode ( currSchema, "dc:subject", kXMP_ExistingOnly );
-		if ( dcSubject != 0 ) {
-                        XMP_OptionBits keepMask = static_cast<XMP_OptionBits>(~(kXMP_PropArrayIsOrdered | kXMP_PropArrayIsAlternate | kXMP_PropArrayIsAltText));
-			dcSubject->options &= keepMask;	// Make sure any ordered array bits are clear.
-		}
-	}
-	
-	// Fix any broken AltText arrays that we know about.
-	
-	RepairAltText ( tree, kXMP_NS_DC, "dc:description" );	// ! Note inclusion of prefixes for direct node lookup!
-	RepairAltText ( tree, kXMP_NS_DC, "dc:rights" );
-	RepairAltText ( tree, kXMP_NS_DC, "dc:title" );
-	RepairAltText ( tree, kXMP_NS_XMP_Rights, "xmpRights:UsageTerms" );
-	RepairAltText ( tree, kXMP_NS_EXIF, "exif:UserComment" );
-	
-	// Tweak old XMP: Move an instance ID from rdf:about to the xmpMM:InstanceID property. An old
-	// instance ID usually looks like "uuid:bac965c4-9d87-11d9-9a30-000d936b79c4", plus InDesign
-	// 3.0 wrote them like "bac965c4-9d87-11d9-9a30-000d936b79c4". If the name looks like a UUID
-	// simply move it to xmpMM:InstanceID, don't worry about any existing xmpMM:InstanceID. Both
-	// will only be present when a newer file with the xmpMM:InstanceID property is updated by an
-	// old app that uses rdf:about.
-	
-	if ( ! tree.name.empty() ) {
-
-		bool nameIsUUID = false;
-		XMP_StringPtr nameStr = tree.name.c_str();
-
-		if ( XMP_LitNMatch ( nameStr, "uuid:", 5 ) ) {
-
-			nameIsUUID = true;
-
-		} else if ( tree.name.size() == 36 ) {
-
-			nameIsUUID = true;	// ! Assume true, we'll set it to false below if not.
-			for ( int i = 0;  i < 36; ++i ) {
-				char ch = nameStr[i];
-				if ( ch == '-' ) {
-					if ( (i == 8) || (i == 13) || (i == 18) || (i == 23) ) continue;
-					nameIsUUID = false;
-					break;
-				} else {
-					if ( (('0' <= ch) && (ch <= '9')) || (('a' <= ch) && (ch <= 'z')) ) continue;
-					nameIsUUID = false;
-					break;
-				}
-			}
-
-		}
-		
-		if ( nameIsUUID ) {
-
-			XMP_ExpandedXPath expPath;
-			ExpandXPath ( kXMP_NS_XMP_MM, "InstanceID", &expPath );
-			XMP_Node * idNode = FindNode ( &tree, expPath, kXMP_CreateNodes, 0 );
-			if ( idNode == 0 ) XMP_Throw ( "Failure creating xmpMM:InstanceID", kXMPErr_InternalFailure );
-
-			idNode->options = 0;	// Clobber any existing xmpMM:InstanceID.
-			idNode->value = tree.name;
-			idNode->RemoveChildren();
-			idNode->RemoveQualifiers();
-
-			tree.name.erase();
-
-		}
-
-	}
-
-}	// TouchUpDataModel
-
-
-// -------------------------------------------------------------------------------------------------
-// DetermineInputEncoding
-// ----------------------
-//
-// Try to determine the character encoding, making a guess if the input is too short. We make some
-// simplifying assumtions: the first character must be U+FEFF or ASCII, U+0000 is not allowed. The
-// XML 1.1 spec is even more strict, UTF-16 XML documents must begin with U+FEFF, and the first
-// "real" character must be '<'. Ignoring the XML declaration, the first XML character could be '<',
-// space, tab, CR, or LF.
-//
-// The possible input sequences are:
-//
-//   Cases with U+FEFF
-//      EF BB BF -- - UTF-8
-//      FE FF -- -- - Big endian UTF-16
-//      00 00 FE FF - Big endian UTF 32
-//      FF FE 00 00 - Little endian UTF-32
-//      FF FE -- -- - Little endian UTF-16
-//
-//   Cases with ASCII
-//      nn mm -- -- - UTF-8 -
-//      00 00 00 nn - Big endian UTF-32
-//      00 nn -- -- - Big endian UTF-16
-//      nn 00 00 00 - Little endian UTF-32
-//      nn 00 -- -- - Little endian UTF-16
-//
-// ! We don't check for full patterns, or for errors. We just check enough to determine what the
-// ! only possible (or reasonable) case would be.
-
-static XMP_OptionBits
-DetermineInputEncoding ( const XMP_Uns8 * buffer, size_t length )
-{
-	if ( length < 2 ) return kXMP_EncodeUTF8;
-	
-	XMP_Uns8 * uniChar = (XMP_Uns8*)buffer;	// ! Make sure comparisons are unsigned.
-	
-	if ( uniChar[0] == 0 ) {
-	
-		// These cases are:
-		//   00 nn -- -- - Big endian UTF-16
-		//   00 00 00 nn - Big endian UTF-32
-		//   00 00 FE FF - Big endian UTF 32
-
-		if ( (length < 4) || (uniChar[1] != 0) ) return kXMP_EncodeUTF16Big;
-		return kXMP_EncodeUTF32Big;
-		
-	} else if ( uniChar[0] < 0x80 ) {
-	
-		// These cases are:
-		//   nn mm -- -- - UTF-8, includes EF BB BF case
-		//   nn 00 00 00 - Little endian UTF-32
-		//   nn 00 -- -- - Little endian UTF-16
-
-		if ( uniChar[1] != 0 )  return kXMP_EncodeUTF8;
-		if ( (length < 4) || (uniChar[2] != 0) ) return kXMP_EncodeUTF16Little;
-		return kXMP_EncodeUTF32Little;
-
-	} else {
-	
-		// These cases are:
-		//   EF BB BF -- - UTF-8
-		//   FE FF -- -- - Big endian UTF-16
-		//   FF FE 00 00 - Little endian UTF-32
-		//   FF FE -- -- - Little endian UTF-16
-
-		if ( uniChar[0] == 0xEF ) return kXMP_EncodeUTF8;
-		if ( uniChar[0] == 0xFE ) return kXMP_EncodeUTF16Big;
-		if ( (length < 4) || (uniChar[2] != 0) ) return kXMP_EncodeUTF16Little;
-		return kXMP_EncodeUTF32Little;
-
-	}
-		
-}	// DetermineInputEncoding
-
-
-// -------------------------------------------------------------------------------------------------
-// CountUTF8
-// ---------
-//
-// Look for a valid multi-byte UTF-8 sequence and return its length. Returns 0 for an invalid UTF-8
-// sequence. Returns a negative value for a partial valid sequence at the end of the buffer.
-//
-// The checking is not strict. We simply count the number of high order 1 bits in the first byte,
-// then look for n-1 following bytes whose high order 2 bits are 1 and 0. We do not check for a
-// minimal length representation of the codepoint, or that the codepoint is defined by Unicode.
-
-static int
-CountUTF8 ( const XMP_Uns8 * charStart, const XMP_Uns8 * bufEnd )
-{
-	XMP_Assert ( charStart < bufEnd );		// Catch this in debug builds.
-	if ( charStart >= bufEnd ) return 0;	// Don't run-on in release builds.
-	if ( (*charStart & 0xC0) != 0xC0 ) return 0;	// Must have at least 2 high bits set.
-	
-	int byteCount = 2;
-	XMP_Uns8 firstByte = *charStart;
-	for ( firstByte = firstByte << 2; (firstByte & 0x80) != 0; firstByte = firstByte << 1 ) ++byteCount;
-	
-	if ( (charStart + byteCount) > bufEnd ) return -byteCount;
-
-	for ( int i = 1; i < byteCount; ++i ) {
-		if ( (charStart[i] & 0xC0) != 0x80 ) return 0;
-	}
-	
-	return byteCount;
-	
-}	// CountUTF8
-
-
-// -------------------------------------------------------------------------------------------------
-// CountControlEscape
-// ------------------
-//
-// Look for a numeric escape sequence for a "prohibited" ASCII control character. These are 0x7F,
-// and the range 0x00..0x1F except for tab/LF/CR. Return 0 if this is definitely not a numeric
-// escape, the length of the escape if found, or a negative value for a partial escape.
-
-static int
-CountControlEscape ( const XMP_Uns8 * escStart, const XMP_Uns8 * bufEnd )
-{
-	XMP_Assert ( escStart < bufEnd );	// Catch this in debug builds.
-	if ( escStart >= bufEnd ) return 0;	// Don't run-on in release builds.
-	XMP_Assert ( *escStart == '&' );
-	
-	size_t tailLen = bufEnd - escStart;
-	if ( tailLen < 5 ) return -1;	// Don't need a more thorough check, we'll catch it on the next pass.
-	
-	if ( strncmp ( (char*)escStart, "&#x", 3 ) != 0 ) return 0;
-	
-	XMP_Uns8 escValue = 0;
-	const XMP_Uns8 * escPos = escStart + 3;
-	
-	if ( ('0' <= *escPos) && (*escPos <= '9') ) {
-		escValue = *escPos - '0';
-		++escPos;
-	} else if ( ('A' <= *escPos) && (*escPos <= 'F') ) {
-		escValue = *escPos - 'A' + 10;
-		++escPos;
-	} else if ( ('a' <= *escPos) && (*escPos <= 'f') ) {
-		escValue = *escPos - 'a' + 10;
-		++escPos;
-	}
-	
-	if ( ('0' <= *escPos) && (*escPos <= '9') ) {
-		escValue = (escValue << 4) + (*escPos - '0');
-		++escPos;
-	} else if ( ('A' <= *escPos) && (*escPos <= 'F') ) {
-		escValue = (escValue << 4) + (*escPos - 'A' + 10);
-		++escPos;
-	} else if ( ('a' <= *escPos) && (*escPos <= 'f') ) {
-		escValue = (escValue << 4) + (*escPos - 'a' + 10);
-		++escPos;
-	}
-	
-	if ( escPos == bufEnd ) return -1;	// Partial escape.
-	if ( *escPos != ';' ) return 0;
-	
-	size_t escLen = escPos - escStart + 1;
-	if ( escLen < 5 ) return 0;	// ! Catch "&#x;".
-	
-	if ( (escValue == kTab) || (escValue == kLF) || (escValue == kCR) ) return 0;	// An allowed escape.
-	
-	return escLen;	// Found a full "prohibited" numeric escape.
-	
-}	// CountControlEscape
-
-
-// -------------------------------------------------------------------------------------------------
-// ProcessUTF8Portion
-// ------------------
-//
-// Early versions of the XMP spec mentioned allowing ISO Latin-1 input. There are also problems with
-// some clients placing ASCII control characters within XMP values. This is an XML problem, the XML
-// spec only allows tab (0x09), LF (0x0A), and CR (0x0D) from the 0x00..0x1F range. As a concession
-// to this we scan 8-bit input for byte sequences that are not valid UTF-8 or in the 0x00..0x1F
-// range and replace each byte as follows:
-//   0x00..0x1F - Replace with a space, except for tab, CR, and LF.
-//   0x7F       - Replace with a space. This is ASCII Delete, not allowed by ISO Latin-1.
-//   0x80..0x9F - Replace with the UTF-8 for a corresponding Unicode character.
-//   0xA0..0XFF - Replace with the UTF-8 for a corresponding Unicode character.
-//
-// The 0x80..0x9F range is not defined by Latin-1. But the Windows 1252 code page defines these and
-// is otherwise the same as Latin-1.
-//
-// For at least historical compatibility reasons we also find and replace singly escaped ASCII
-// control characters. The Expat parser we're using does not allow numeric escapes like "&#x10;".
-// The XML spec is clear that raw controls are not allowed (in the RestrictedChar set), but it isn't
-// as clear about numeric escapes for them. At any rate, Expat complains, so we treat the numeric
-// escapes like raw characters and replace them with a space.
-//
-// We check for 1 or 2 hex digits ("&#x9;" or "&#x09;") and upper or lower case ("&#xA;" or "&#xa;").
-// The full escape sequence is 5 or 6 bytes.
-
-static size_t
-ProcessUTF8Portion ( XMLParserAdapter * xmlParser,
-					 const XMP_Uns8 *   buffer,
-					 size_t				length,
-					 bool				last )
-{
-	const XMP_Uns8 * bufEnd = buffer + length;
-	
-	const XMP_Uns8 * spanStart = buffer;
-	const XMP_Uns8 * spanEnd;
-		
-	for ( spanEnd = spanStart; spanEnd < bufEnd; ++spanEnd ) {
-
-		if ( (0x20 <= *spanEnd) && (*spanEnd <= 0x7E) && (*spanEnd != '&') ) continue;	// A regular ASCII character.
-
-		if ( *spanEnd >= 0x80 ) {
-		
-			// See if this is a multi-byte UTF-8 sequence, or a Latin-1 character to replace.
-
-			int uniLen = CountUTF8 ( spanEnd, bufEnd );
-
-			if ( uniLen > 0 ) {
-
-				// A valid UTF-8 character, keep it as-is.
-				spanEnd += uniLen - 1;	// ! The loop increment will put back the +1.
-
-			} else if ( (uniLen < 0) && (! last) ) {
-
-				// Have a partial UTF-8 character at the end of the buffer and more input coming.
-				xmlParser->ParseBuffer ( spanStart, (spanEnd - spanStart), false );
-				return (spanEnd - buffer);
-
-			} else {
-
-				// Not a valid UTF-8 sequence. Replace the first byte with the Latin-1 equivalent.
-				xmlParser->ParseBuffer ( spanStart, (spanEnd - spanStart), false );
-				const char * replacement = kReplaceLatin1 [ *spanEnd - 0x80 ];
-				xmlParser->ParseBuffer ( replacement, strlen ( replacement ), false );
-				spanStart = spanEnd + 1;	// ! The loop increment will do "spanEnd = spanStart".
-
-			}
-		
-		} else if ( (*spanEnd < 0x20) || (*spanEnd == 0x7F) ) {
-
-			// Replace ASCII controls other than tab, LF, and CR with a space.
-
-			if ( (*spanEnd == kTab) || (*spanEnd == kLF) || (*spanEnd == kCR) ) continue;
-
-			xmlParser->ParseBuffer ( spanStart, (spanEnd - spanStart), false );
-			xmlParser->ParseBuffer ( " ", 1, false );
-			spanStart = spanEnd + 1;	// ! The loop increment will do "spanEnd = spanStart".
-		
-		} else {
-		
-			// See if this is a numeric escape sequence for a prohibited ASCII control.
-			
-			XMP_Assert ( *spanEnd == '&' );
-			int escLen = CountControlEscape ( spanEnd, bufEnd );
-			
-			if ( escLen < 0 ) {
-
-				// Have a partial numeric escape in this buffer, wait for more input.
-				if ( last ) continue;	// No more buffers, not an escape, absorb as normal input.
-				xmlParser->ParseBuffer ( spanStart, (spanEnd - spanStart), false );
-				return (spanEnd - buffer);
-
-			} else if ( escLen > 0 ) {
-
-				// Have a complete numeric escape to replace.
-				xmlParser->ParseBuffer ( spanStart, (spanEnd - spanStart), false );
-				xmlParser->ParseBuffer ( " ", 1, false );
-				spanStart = spanEnd + escLen;
-				spanEnd = spanStart - 1;	// ! The loop continuation will increment spanEnd!
-
-			}
-
-		}
-		
-	}
-	
-	XMP_Assert ( spanEnd == bufEnd );
-
-	if ( spanStart < bufEnd ) xmlParser->ParseBuffer ( spanStart, (spanEnd - spanStart), false );
-	if ( last ) xmlParser->ParseBuffer ( " ", 1, true );
-	
-	return length;
-
-}	// ProcessUTF8Portion
-
-
-// -------------------------------------------------------------------------------------------------
-// ParseFromBuffer
-// ---------------
-//
-// Although most clients will probably parse everything in one call, we have a buffered API model
-// and need to support even the extreme case of 1 byte at a time parsing. This is considerably
-// complicated by some special cases for 8-bit input. Because of this, the first thing we do is
-// determine whether the input is 8-bit, UTF-16, or UTF-32.
-//
-// Both the 8-bit special cases and the encoding determination are easier to do with 8 bytes or more
-// of input. The XMLParserAdapter class has a pending-input buffer for this. At the start of parsing
-// we (moght) try to fill this buffer before determining the input character encoding. After that,
-// we (might) use this buffer with the current input to simplify the logic in Process8BitInput. The
-// "(might)" part means that we don't actually use the pending-input buffer unless we have to. In
-// particular, the common case of single-buffer parsing won't use it.
-
-void
-XMPMeta::ParseFromBuffer ( XMP_StringPtr  buffer,
-						   XMP_StringLen  xmpSize,
-						   XMP_OptionBits options )
-{
-	if ( (buffer == 0) && (xmpSize != 0) ) XMP_Throw ( "Null parse buffer", kXMPErr_BadParam );
-	if ( xmpSize == kXMP_UseNullTermination ) xmpSize = strlen ( buffer );
-	
-	const bool lastClientCall = ((options & kXMP_ParseMoreBuffers) == 0);	// *** Could use FlagIsSet & FlagIsClear macros.
-	
-	this->tree.ClearNode();	// Make sure the target XMP object is totally empty.
-
-	if ( this->xmlParser == 0 ) {
-		if ( (xmpSize == 0) && lastClientCall ) return;	// Tolerate empty parse. Expat complains if there are no XML elements.
-		this->xmlParser = XMP_NewExpatAdapter();
-	}
-	
-	XMLParserAdapter& parser = *this->xmlParser;
-	
-	#if 0	// XMP_DebugBuild
-		if ( parser.parseLog != 0 ) {
-			char message [200];	// AUDIT: Using sizeof(message) below for snprintf length is safe.
-			snprintf ( message, sizeof(message), "<!-- ParseFromBuffer, length = %d, options = %X%s -->",	// AUDIT: See above.
-					   xmpSize, options, (lastClientCall ? " (last)" : "") );
-			fwrite ( message, 1, strlen(message), parser.parseLog );
-			fflush ( parser.parseLog );
-		}
-	#endif
-		
-	try {	// Cleanup the tree and xmlParser if anything fails.
-	
-		// Determine the character encoding before doing any real parsing. This is needed to do the
-		// 8-bit special processing.
-		
-		if ( parser.charEncoding == XMP_OptionBits(-1) ) {
-
-			if ( (parser.pendingCount == 0) && (xmpSize >= kXMLPendingInputMax) ) {
-
-				// This ought to be the common case, the first buffer is big enough.
-				parser.charEncoding = DetermineInputEncoding ( (XMP_Uns8*)buffer, xmpSize );
-
-			} else {
-			
-				// Try to fill the pendingInput buffer before calling DetermineInputEncoding.
-
-				size_t pendingOverlap = kXMLPendingInputMax - parser.pendingCount;
-				if ( pendingOverlap > xmpSize ) pendingOverlap = xmpSize;
-
-				memcpy ( &parser.pendingInput[parser.pendingCount], buffer, pendingOverlap );	// AUDIT: Count is safe.
-				buffer += pendingOverlap;
-				xmpSize -= pendingOverlap;
-				parser.pendingCount += pendingOverlap;
-
-				if ( (! lastClientCall) && (parser.pendingCount < kXMLPendingInputMax) ) return;
-				parser.charEncoding = DetermineInputEncoding ( parser.pendingInput, parser.pendingCount );
-				
-				#if Trace_ParsingHackery
-					fprintf ( stderr, "XMP Character encoding is %d\n", parser.charEncoding );
-				#endif
-			
-			}
-
-		}
-		
-		// We have the character encoding. Process UTF-16 and UTF-32 as is. UTF-8 needs special
-		// handling to take care of things like ISO Latin-1 or unescaped ASCII controls.
-
-		XMP_Assert ( parser.charEncoding != XMP_OptionBits(-1) );
-
-		if ( parser.charEncoding != kXMP_EncodeUTF8 ) {
-		
-			if ( parser.pendingCount > 0 ) {
-				// Might have pendingInput from the above portion to determine the character encoding.
-				parser.ParseBuffer ( parser.pendingInput, parser.pendingCount, false );
-			}
-			parser.ParseBuffer ( buffer, xmpSize, lastClientCall );
-			
-		} else {
-
-			#if Trace_ParsingHackery
-				fprintf ( stderr, "Parsing %d bytes @ %.8X, %s, %d pending, context: %.8s\n",
-						  xmpSize, buffer, (lastClientCall ? "last" : "not last"), parser.pendingCount, buffer );
-			#endif
-
-			// The UTF-8 processing is a bit complex due to the need to tolerate ISO Latin-1 input.
-			// This is done by scanning the input for byte sequences that are not valid UTF-8,
-			// assuming they are Latin-1 characters in the range 0x80..0xFF. This requires saving a
-			// pending input buffer to handle partial UTF-8 sequences at the end of a buffer.
-			
-			while ( parser.pendingCount > 0 ) {
-			
-				// We've got some leftover input, process it first then continue with the current
-				// buffer. Try to fill the pendingInput buffer before parsing further. We use a loop
-				// for weird edge cases like a 2 byte input buffer, using 1 byte for pendingInput,
-				// then having a partial UTF-8 end and need to absorb more.
-				
-				size_t pendingOverlap = kXMLPendingInputMax - parser.pendingCount;
-				if ( pendingOverlap > xmpSize ) pendingOverlap = xmpSize;
-				
-				memcpy ( &parser.pendingInput[parser.pendingCount], buffer, pendingOverlap );	// AUDIT: Count is safe.
-				parser.pendingCount += pendingOverlap;
-				buffer += pendingOverlap;
-				xmpSize -= pendingOverlap;
-
-				if ( (! lastClientCall) && (parser.pendingCount < kXMLPendingInputMax) ) return;
-				size_t bytesDone = ProcessUTF8Portion ( &parser, parser.pendingInput, parser.pendingCount, lastClientCall );
-				size_t bytesLeft = parser.pendingCount - bytesDone;
-
-				#if Trace_ParsingHackery
-					fprintf ( stderr, "   ProcessUTF8Portion handled %d pending bytes\n", bytesDone );
-				#endif
-				
-				if ( bytesDone == parser.pendingCount ) {
-
-					// Done with all of the pending input, move on to the current buffer.
-					parser.pendingCount = 0;
-
-				} else if ( bytesLeft <= pendingOverlap ) {
-
-					// The leftover pending input all came from the current buffer. Exit this loop.
-					buffer -= bytesLeft;
-					xmpSize += bytesLeft;
-					parser.pendingCount = 0;
-
-				} else if ( xmpSize > 0 ) {
-
-					// Pull more of the current buffer into the pending input and try again.
-					// Backup by this pass's overlap so the loop entry code runs OK.
-					parser.pendingCount -= pendingOverlap;
-					buffer -= pendingOverlap;
-					xmpSize += pendingOverlap;
-
-				} else {
-
-					// There is no more of the current buffer. Wait for more. Partial sequences at
-					// the end of the last buffer should be treated as Latin-1 by ProcessUTF8Portion.
-					XMP_Assert ( ! lastClientCall );
-					parser.pendingCount = bytesLeft;
-					memcpy ( &parser.pendingInput[0], &parser.pendingInput[bytesDone], bytesLeft );	// AUDIT: Count is safe.
-					return;
-
-				}
-			
-			}
-			
-			// Done with the pending input, process the current buffer.
-
-			size_t bytesDone = ProcessUTF8Portion ( &parser, (XMP_Uns8*)buffer, xmpSize, lastClientCall );
-
-			#if Trace_ParsingHackery
-				fprintf ( stderr, "   ProcessUTF8Portion handled %d additional bytes\n", bytesDone );
-			#endif
-			
-			if ( bytesDone < xmpSize ) {
-
-				XMP_Assert ( ! lastClientCall );
-				size_t bytesLeft = xmpSize - bytesDone;
-				if ( bytesLeft > kXMLPendingInputMax ) XMP_Throw ( "Parser bytesLeft too large", kXMPErr_InternalFailure );
-
-				memcpy ( parser.pendingInput, &buffer[bytesDone], bytesLeft );	// AUDIT: Count is safe.
-				parser.pendingCount = bytesLeft;
-				return;	// Wait for the next buffer.
-
-			}
-
-		}
-		
-		if ( lastClientCall ) {
-		
-			#if XMP_DebugBuild && DumpXMLParseTree
-				if ( parser.parseLog == 0 ) parser.parseLog = stdout;
-				DumpXMLTree ( parser.parseLog, parser.tree, 0 );
-			#endif
-
-			const XML_Node * xmlRoot = FindRootNode ( this, *this->xmlParser, options );
-
-			if ( xmlRoot != 0 ) {
-
-				ProcessRDF ( &this->tree, *xmlRoot, options );
-				NormalizeDCArrays ( &this->tree );
-				if ( this->tree.options & kXMP_PropHasAliases ) MoveExplicitAliases ( &this->tree, options );
-				TouchUpDataModel ( this );
-				
-				// Delete empty schema nodes. Do this last, other cleanup can make empty schema.
-				size_t schemaNum = 0;
-				while ( schemaNum < this->tree.children.size() ) {
-					XMP_Node * currSchema = this->tree.children[schemaNum];
-					if ( currSchema->children.size() > 0 ) {
-						++schemaNum;
-					} else {
-						delete this->tree.children[schemaNum];	// ! Delete the schema node itself.
-						this->tree.children.erase ( this->tree.children.begin() + schemaNum );
-					}
-				}
-				
-			}
-
-			delete this->xmlParser;
-			this->xmlParser = 0;
-
-		}
-		
-	} catch ( ... ) {
-
-		delete this->xmlParser;
-		this->xmlParser = 0;
-		prevTkVer = 0;
-		this->tree.ClearNode();
-		throw;
-
-	}
-	
-}	// ParseFromBuffer
-
-// =================================================================================================
diff --git a/xmpsdk/src/XMPMeta-Serialize.cpp b/xmpsdk/src/XMPMeta-Serialize.cpp
deleted file mode 100644
index 70a7b020..00000000
--- a/xmpsdk/src/XMPMeta-Serialize.cpp
+++ /dev/null
@@ -1,1342 +0,0 @@
-// ================================================================================================= // Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-//
-// Adobe patent application tracking #P435, entitled 'Unique markers to simplify embedding data of
-// one format in a file with a different format', inventors: Sean Parent, Greg Gilley.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-
-#include "XMPMeta.hpp"
-
-#include "XMP_Version.h"
-#include "UnicodeInlines.incl_cpp"
-#include "UnicodeConversions.hpp"
-
-#if XMP_DebugBuild
-	#include <iostream>
-#endif
-
-using namespace std;
-
-#if XMP_WinBuild
-#ifdef _MSC_VER
-	#pragma warning ( disable : 4533 )	// initialization of '...' is skipped by 'goto ...'
-	#pragma warning ( disable : 4702 )	// unreachable code
-	#pragma warning ( disable : 4800 )	// forcing value to bool 'true' or 'false' (performance warning)
-#endif
-#endif
-
-// *** Use the XMP_PropIsXyz (Schema, Simple, Struct, Array, ...) macros
-// *** Add debug codegen checks, e.g. that typical masking operations really work
-// *** Change all uses of strcmp and strncmp to XMP_LitMatch and XMP_LitNMatch
-
-
-// =================================================================================================
-// Local Types and Constants
-// =========================
-
-static const char * kPacketHeader  = "<?xpacket begin=\"\xEF\xBB\xBF\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>";
-static const char * kPacketTrailer = "<?xpacket end=\"w\"?>";	// ! The w/r is at [size-4].
-
-static const char * kRDF_XMPMetaStart = "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"";
-static const char * kRDF_XMPMetaEnd   = "</x:xmpmeta>";
-
-static const char * kRDF_RDFStart     = "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">";
-static const char * kRDF_RDFEnd       = "</rdf:RDF>";
-
-static const char * kRDF_SchemaStart  = "<rdf:Description rdf:about=";
-static const char * kRDF_SchemaEnd    = "</rdf:Description>";
-
-static const char * kRDF_StructStart  = "<rdf:Description>";
-static const char * kRDF_StructEnd    = "</rdf:Description>";
-
-static const char * kRDF_BagStart     = "<rdf:Bag>";
-
-static const char * kRDF_ItemStart    = "<rdf:li>";
-
-static const char * kRDF_ValueStart   = "<rdf:value>";
-
-
-// =================================================================================================
-// Static Variables
-// ================
-
-
-// =================================================================================================
-// Local Utilities
-// ===============
-
-
-// -------------------------------------------------------------------------------------------------
-// EstimateRDFSize
-// ---------------
-
-//  *** Pull the strlen(kXyz) calls into constants.
-
-static size_t
-EstimateRDFSize ( const XMP_Node * currNode, XMP_Index indent, size_t indentLen )
-{
-	size_t outputLen = 2 * (indent*indentLen + currNode->name.size() + 4);	// The property element tags.
-	
-	if ( ! currNode->qualifiers.empty() ) {
-		// This node has qualifiers, assume it is written using rdf:value and estimate the qualifiers.
-
-		indent += 2;	// Everything else is indented inside the rdf:Description element.
-		outputLen += 2 * ((indent-1)*indentLen + strlen(kRDF_StructStart) + 2);	// The rdf:Description tags.
-		outputLen += 2 * (indent*indentLen + strlen(kRDF_ValueStart) + 2);		// The rdf:value tags.
-
-		for ( size_t qualNum = 0, qualLim = currNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
-			const XMP_Node * currQual = currNode->qualifiers[qualNum];
-			outputLen += EstimateRDFSize ( currQual, indent, indentLen );
-		}
-
-	}
-	
-	if ( currNode->options & kXMP_PropValueIsStruct ) {
-		indent += 1;
-		outputLen += 2 * (indent*indentLen + strlen(kRDF_StructStart) + 2);	// The rdf:Description tags.
-	} else if ( currNode->options & kXMP_PropValueIsArray ) {
-		indent += 2;
-		outputLen += 2 * ((indent-1)*indentLen + strlen(kRDF_BagStart) + 2);		// The rdf:Bag/Seq/Alt tags.
-		outputLen += 2 * currNode->children.size() * (strlen(kRDF_ItemStart) + 2);	// The rdf:li tags, indent counted in children.
-	} else if ( ! (currNode->options & kXMP_SchemaNode) ) {
-		outputLen += currNode->value.size();	// This is a leaf value node.
-	}
-
-	for ( size_t childNum = 0, childLim = currNode->children.size(); childNum < childLim; ++childNum ) {
-		const XMP_Node * currChild = currNode->children[childNum];
-		outputLen += EstimateRDFSize ( currChild, indent+1, indentLen );
-	}
-
-	return outputLen;
-	
-}	// EstimateRDFSize
-
-
-// -------------------------------------------------------------------------------------------------
-// DeclareOneNamespace
-// -------------------
-
-static void
-DeclareOneNamespace	( const XMP_VarString &	nsPrefix,
-					  const XMP_VarString &	nsURI,
-					  XMP_VarString	&		usedNS,		// ! A catenation of the prefixes with colons.
-					  XMP_VarString &		outputStr,
-					  XMP_StringPtr			newline,
-					  XMP_StringPtr			indentStr,
-					  XMP_Index				indent )
-{
-	size_t nsPos = usedNS.find ( nsPrefix );
-
-	if ( nsPos == XMP_VarString::npos ) {
-		
-		outputStr += newline;
-		for ( ; indent > 0; --indent ) outputStr += indentStr;
-		outputStr += "xmlns:";
-		outputStr += nsPrefix;
-		outputStr[outputStr.size()-1] = '=';	// Change the colon to =.
-		outputStr += '"';
-		outputStr += nsURI;
-		outputStr += '"';
-
-		usedNS += nsPrefix;
-
-	}
-
-}	// DeclareOneNamespace
-
-
-// -------------------------------------------------------------------------------------------------
-// DeclareElemNamespace
-// --------------------
-
-static void
-DeclareElemNamespace ( const XMP_VarString & elemName,
-					   XMP_VarString &		 usedNS,
-					   XMP_VarString &		 outputStr,
-					   XMP_StringPtr		 newline,
-					   XMP_StringPtr		 indentStr,
-					   XMP_Index			 indent )
-{
-	size_t colonPos = elemName.find ( ':' );
-
-	if ( colonPos != XMP_VarString::npos ) {
-		XMP_VarString nsPrefix ( elemName.substr ( 0, colonPos+1 ) );
-		XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( nsPrefix );
-		XMP_Enforce ( prefixPos != sNamespacePrefixToURIMap->end() );
-		DeclareOneNamespace ( nsPrefix, prefixPos->second, usedNS, outputStr, newline, indentStr, indent );
-	}
-
-}	// DeclareElemNamespace
-
-
-// -------------------------------------------------------------------------------------------------
-// DeclareUsedNamespaces
-// ---------------------
-
-// ??? Should iterators be passed by reference to avoid temp copies?
-
-static void
-DeclareUsedNamespaces ( const XMP_Node * currNode,
-						XMP_VarString &  usedNS,
-						XMP_VarString &	 outputStr,
-						XMP_StringPtr	 newline,
-						XMP_StringPtr	 indentStr,
-						XMP_Index		 indent )
-{
-
-	if ( currNode->options & kXMP_SchemaNode ) {
-		// The schema node name is the URI, the value is the prefix.
-		DeclareOneNamespace ( currNode->value, currNode->name, usedNS, outputStr, newline, indentStr, indent );
-	} else if ( currNode->options & kXMP_PropValueIsStruct ) {
-		for ( size_t fieldNum = 0, fieldLim = currNode->children.size(); fieldNum < fieldLim; ++fieldNum ) {
-			const XMP_Node * currField = currNode->children[fieldNum];
-			DeclareElemNamespace ( currField->name, usedNS, outputStr, newline, indentStr, indent );
-		}
-	}
-
-	for ( size_t childNum = 0, childLim = currNode->children.size(); childNum < childLim; ++childNum ) {
-		const XMP_Node * currChild = currNode->children[childNum];
-		DeclareUsedNamespaces ( currChild, usedNS, outputStr, newline, indentStr, indent );
-	}
-
-	for ( size_t qualNum = 0, qualLim = currNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
-		const XMP_Node * currQual = currNode->qualifiers[qualNum];
-		DeclareElemNamespace ( currQual->name, usedNS, outputStr, newline, indentStr, indent );
-		DeclareUsedNamespaces ( currQual, usedNS, outputStr, newline, indentStr, indent );
-	}
-	
-}	// DeclareUsedNamespaces
-
-// -------------------------------------------------------------------------------------------------
-// EmitRDFArrayTag
-// ---------------
-
-// ??? Should iterators be passed by reference to avoid temp copies?
-
-enum {
-	kIsStartTag = true,
-	kIsEndTag   = false
-};
-
-static void
-EmitRDFArrayTag	( XMP_OptionBits  arrayForm,
-				  XMP_VarString & outputStr,
-				  XMP_StringPtr	  newline,
-				  XMP_StringPtr	  indentStr,
-				  XMP_Index		  indent,
-				  XMP_Index		  arraySize,
-				  bool			  isStartTag )
-{
-	if ( (! isStartTag) && (arraySize == 0) ) return;
-	
-	for ( XMP_Index level = indent; level > 0; --level ) outputStr += indentStr;
-	if ( isStartTag ) {
-		outputStr += "<rdf:";
-	} else {
-		outputStr += "</rdf:";
-	}
-
-	if ( arrayForm & kXMP_PropArrayIsAlternate ) {
-		outputStr += "Alt";
-	} else if ( arrayForm & kXMP_PropArrayIsOrdered ) {
-		outputStr += "Seq";
-	} else {
-		outputStr += "Bag";
-	}
-	
-	if ( isStartTag && (arraySize == 0) ) outputStr += '/';
-	outputStr += '>';
-	outputStr += newline;
-
-}	// EmitRDFArrayTag
-
-
-// -------------------------------------------------------------------------------------------------
-// AppendNodeValue
-// ---------------
-//
-// Append a property or qualifier value to the output with appropriate XML escaping. The escaped
-// characters for elements and attributes are '&', '<', '>', and ASCII controls (tab, LF, CR). In
-// addition, '"' is escaped for attributes. For efficiency, this is done in a double loop. The outer
-// loop makes sure the whole value is processed. The inner loop does a contiguous unescaped run
-// followed by one escaped character (if we're not at the end).
-//
-// We depend on parsing and SetProperty logic to make sure there are no invalid ASCII controls in
-// the XMP values. The XML spec only allows tab, LF, and CR. Others are not even allowed as
-// numeric escape sequences.
-
-enum {
-	kForAttribute = true,
-	kForElement   = false
-};
-
-static void
-AppendNodeValue ( XMP_VarString & outputStr, const XMP_VarString & value, bool forAttribute )
-{
-
-	unsigned char * runStart = (unsigned char *) value.c_str();
-	unsigned char * runLimit  = runStart + value.size();
-	unsigned char * runEnd;
-	unsigned char   ch=0;
-	
-	while ( runStart < runLimit ) {
-	
-		for ( runEnd = runStart; runEnd < runLimit; ++runEnd ) {
-			ch = *runEnd;
-			if ( forAttribute && (ch == '"') ) break;
-			if ( (ch < 0x20) || (ch == '&') || (ch == '<') || (ch == '>') ) break;
-		}
-		
-		outputStr.append ( (char *) runStart, (runEnd - runStart) );
-		
-		if ( runEnd < runLimit ) {
-
-			if ( ch < 0x20 ) {
-			
-				XMP_Assert ( (ch == kTab) || (ch == kLF) || (ch == kCR) );
-
-				char hexBuf[16];
-				memcpy ( hexBuf, "&#xn;", 5 );
-				hexBuf[3] = kHexDigits[ch&0xF];
-				outputStr.append ( hexBuf, 5 );
-
-			} else {
-
-				if ( ch == '"' ) {
-					outputStr += "&quot;";
-				} else if ( ch == '<' ) {
-					outputStr += "&lt;";
-				} else if ( ch == '>' ) {
-					outputStr += "&gt;";
-				} else {
-					XMP_Assert ( ch == '&' );
-					outputStr += "&amp;";
-				}
-
-			}
-
-			++runEnd;
-
-		}
-		
-		runStart = runEnd;
-	
-	}
-
-}	// AppendNodeValue
-
-
-// -------------------------------------------------------------------------------------------------
-// CanBeRDFAttrProp
-// ----------------
-
-static bool
-CanBeRDFAttrProp ( const XMP_Node * propNode )
-{
-	
-	if ( propNode->name[0] == '[' ) return false;
-	if ( ! propNode->qualifiers.empty() ) return false;
-	if ( propNode->options & kXMP_PropValueIsURI ) return false;
-	if ( propNode->options & kXMP_PropCompositeMask ) return false;
-	
-	return true;
-	
-}	// CanBeRDFAttrProp
-
-
-// -------------------------------------------------------------------------------------------------
-// IsRDFAttrQualifier
-// ------------------
-
-static XMP_StringPtr sAttrQualifiers[] = { "xml:lang", "rdf:resource", "rdf:ID", "rdf:bagID", "rdf:nodeID", "" };
-
-static bool
-IsRDFAttrQualifier ( XMP_VarString qualName )
-{
-
-	for ( size_t i = 0; *sAttrQualifiers[i] != 0; ++i ) {
-		if ( qualName == sAttrQualifiers[i] ) return true;
-	}
-
-	return false;
-	
-}	// IsRDFAttrQualifier
-
-
-// -------------------------------------------------------------------------------------------------
-// SerializePrettyRDFProperty
-// --------------------------
-//
-// Recursively handles the "value" for a node. It does not matter if it is a top level property, a
-// field of a struct, or an item of an array.  The indent is that for the property element. An
-// xml:lang qualifier is written as an attribute of the property start tag, not by itself forcing
-// the qualified property form. The patterns below mostly ignore attribute qualifiers like xml:lang.
-// Except for the one struct case, attribute qualifiers don't affect the output form.
-//
-//	<ns:UnqualifiedSimpleProperty>value</ns:UnqualifiedSimpleProperty>
-//
-//	<ns:UnqualifiedStructProperty rdf:parseType="Resource">	(If no rdf:resource qualifier)
-//		... Fields, same forms as top level properties
-//	</ns:UnqualifiedStructProperty>
-//
-//	<ns:ResourceStructProperty rdf:resource="URI"
-//		... Fields as attributes
-//	>
-//
-//	<ns:UnqualifiedArrayProperty>
-//		<rdf:Bag> or Seq or Alt
-//			... Array items as rdf:li elements, same forms as top level properties
-//		</rdf:Bag>
-//	</ns:UnqualifiedArrayProperty>
-//
-//	<ns:QualifiedProperty rdf:parseType="Resource">
-//		<rdf:value> ... Property "value" following the unqualified forms ... </rdf:value>
-//		... Qualifiers looking like named struct fields
-//	</ns:QualifiedProperty>
-
-static void
-SerializePrettyRDFProperty ( const XMP_Node * propNode,
-							 XMP_VarString &  outputStr,
-							 XMP_StringPtr	  newline,
-							 XMP_StringPtr	  indentStr,
-							 XMP_Index		  indent,
-							 bool			  emitAsRDFValue = false )
-{
-	XMP_Index level;
-	bool emitEndTag   = true;
-	bool indentEndTag = true;
-
-	XMP_OptionBits propForm = propNode->options & kXMP_PropCompositeMask;
-
-	// ------------------------------------------------------------------------------------------
-	// Determine the XML element name. Open the start tag with the name and attribute qualifiers.
-	
-	XMP_StringPtr elemName = propNode->name.c_str();
-	if ( emitAsRDFValue ) {
-		elemName= "rdf:value";
-	} else if ( *elemName == '[' ) {
-		elemName = "rdf:li";
-	}
-
-	for ( level = indent; level > 0; --level ) outputStr += indentStr;
-	outputStr += '<';
-	outputStr += elemName;
-	
-	#define isCompact	false
-	bool hasGeneralQualifiers = isCompact;	// Might also become true later.
-	bool hasRDFResourceQual   = false;
-	
-	for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
-		const XMP_Node * currQual = propNode->qualifiers[qualNum];
-		if ( ! IsRDFAttrQualifier ( currQual->name ) ) {
-			hasGeneralQualifiers = true;
-		} else {
-			if ( currQual->name == "rdf:resource" ) hasRDFResourceQual = true;
-			if ( ! emitAsRDFValue ) {
-				outputStr += ' ';
-				outputStr += currQual->name;
-				outputStr += "=\"";
-				AppendNodeValue ( outputStr, currQual->value, kForAttribute );
-				outputStr += '"';
-			}
-		}
-	}
-	
-	// --------------------------------------------------------
-	// Process the property according to the standard patterns.
-	
-	if ( hasGeneralQualifiers && (! emitAsRDFValue) ) {
-	
-		// -----------------------------------------------------------------------------------------
-		// This node has general, non-attribute, qualifiers. Emit using the qualified property form.
-		// ! The value is output by a recursive call ON THE SAME NODE with emitAsRDFValue set.
-
-		if ( hasRDFResourceQual ) {
-			XMP_Throw ( "Can't mix rdf:resource and general qualifiers", kXMPErr_BadRDF );
-		}
-		
-		outputStr += " rdf:parseType=\"Resource\">";
-		outputStr += newline;
-
-		SerializePrettyRDFProperty ( propNode, outputStr, newline, indentStr, indent+1, true );
-		
-		for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
-			const XMP_Node * currQual = propNode->qualifiers[qualNum];
-			if ( IsRDFAttrQualifier ( currQual->name ) ) continue;
-			SerializePrettyRDFProperty ( currQual, outputStr, newline, indentStr, indent+1 );
-		}
-		
-	} else {
-
-		// --------------------------------------------------------------------
-		// This node has no general qualifiers. Emit using an unqualified form.
-		
-		if ( propForm == 0 ) {
-		
-			// --------------------------
-			// This is a simple property.
-			
-			if ( propNode->options & kXMP_PropValueIsURI ) {
-				outputStr += " rdf:resource=\"";
-				AppendNodeValue ( outputStr, propNode->value, kForAttribute );
-				outputStr += "\"/>";
-				outputStr += newline;
-				emitEndTag = false;
-			} else if ( propNode->value.empty() ) {
-				outputStr += "/>";
-				outputStr += newline;
-				emitEndTag = false;
-			} else {
-				outputStr += '>';
-				AppendNodeValue ( outputStr, propNode->value, kForElement );
-				indentEndTag = false;
-			}
-			
-		} else if ( propForm & kXMP_PropValueIsArray ) {
-		
-			// This is an array.
-			outputStr += '>';
-			outputStr += newline;
-			EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsStartTag );
-			if ( XMP_ArrayIsAltText(propNode->options) ) NormalizeLangArray ( (XMP_Node*)propNode );
-			for ( size_t childNum = 0, childLim = propNode->children.size(); childNum < childLim; ++childNum ) {
-				const XMP_Node * currChild = propNode->children[childNum];
-				SerializePrettyRDFProperty ( currChild, outputStr, newline, indentStr, indent+2 );
-			}
-			EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsEndTag );
-		
-		
-		} else if ( ! hasRDFResourceQual ) {
-		
-			// This is a "normal" struct, use the rdf:parseType="Resource" form.
-			XMP_Assert ( propForm & kXMP_PropValueIsStruct );
-			if ( propNode->children.size() == 0 ) {
-				outputStr += " rdf:parseType=\"Resource\"/>";
-				outputStr += newline;
-				emitEndTag = false;
-			} else {
-				outputStr += " rdf:parseType=\"Resource\">";
-				outputStr += newline;
-				for ( size_t childNum = 0, childLim = propNode->children.size(); childNum < childLim; ++childNum ) {
-					const XMP_Node * currChild = propNode->children[childNum];
-					SerializePrettyRDFProperty ( currChild, outputStr, newline, indentStr, indent+1 );
-				}
-			}
-		
-		} else {
-		
-			// This is a struct with an rdf:resource attribute, use the "empty property element" form.
-			XMP_Assert ( propForm & kXMP_PropValueIsStruct );
-			for ( size_t childNum = 0, childLim = propNode->children.size(); childNum < childLim; ++childNum ) {
-				const XMP_Node * currChild = propNode->children[childNum];
-				if ( ! CanBeRDFAttrProp ( currChild ) ) {
-					XMP_Throw ( "Can't mix rdf:resource and complex fields", kXMPErr_BadRDF );
-				}
-				outputStr += newline;
-				for ( level = indent+1; level > 0; --level ) outputStr += indentStr;
-				outputStr += ' ';
-				outputStr += currChild->name;
-				outputStr += "=\"";
-				outputStr += currChild->value;
-				outputStr += '"';
-			}
-			outputStr += "/>";
-			outputStr += newline;
-			emitEndTag = false;
-		
-		}
-		
-	}
-	
-	// ----------------------------------
-	// Emit the property element end tag.
-	
-	if ( emitEndTag ) {
-		if ( indentEndTag ) for ( level = indent; level > 0; --level ) outputStr += indentStr;
-		outputStr += "</";
-		outputStr += elemName;
-		outputStr += '>';
-		outputStr += newline;
-	}
-	
-}	// SerializePrettyRDFProperty
-
-
-// -------------------------------------------------------------------------------------------------
-// SerializePrettyRDFSchema
-// ------------------------
-//
-// Each schema's properties are written in a separate rdf:Description element. All of the necessary
-// namespaces are declared in the rdf:Description element. The baseIndent is the base level for the
-// entire serialization, that of the x:xmpmeta element. An xml:lang qualifier is written as an
-// attribute of the property start tag, not by itself forcing the qualified property form.
-//
-//	<rdf:Description rdf:about="TreeName"
-//			xmlns:ns="URI" ... >
-//
-//		... The actual properties of the schema, see SerializePrettyRDFProperty
-//
-//		<!-- ns1:Alias is aliased to ns2:Actual -->  ... If alias comments are wanted
-//
-//	</rdf:Description>
-
-static void
-SerializePrettyRDFSchema ( const XMP_VarString & treeName,
-						   const XMP_Node *		 schemaNode,
-						   XMP_VarString &		 outputStr,
-						   XMP_OptionBits		 options,
-						   XMP_StringPtr		 newline,
-						   XMP_StringPtr		 indentStr,
-						   XMP_Index			 baseIndent )
-{
-	XMP_Assert ( schemaNode->options & kXMP_SchemaNode );
-	XMP_Assert ( schemaNode->qualifiers.empty() );
-	
-	// Write the rdf:Description start tag with the namespace declarations.
-	
-	XMP_Index level;
-	for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr;
-	outputStr += kRDF_SchemaStart;
-	outputStr += '"';
-	outputStr += treeName;
-	outputStr += '"';
-
-	size_t totalLen = 8;	// Start at 8 for "xml:rdf:".
-	XMP_cStringMapPos currPos = sNamespacePrefixToURIMap->begin();
-	XMP_cStringMapPos endPos  = sNamespacePrefixToURIMap->end();
-	for ( ; currPos != endPos; ++currPos ) totalLen += currPos->first.size();
-
-	XMP_VarString usedNS;
-	usedNS.reserve ( totalLen );
-	usedNS = "xml:rdf:";
-	DeclareUsedNamespaces ( schemaNode, usedNS, outputStr, newline, indentStr, baseIndent+4 );
-
-	outputStr += ">";
-	outputStr += newline;
-	
-	// Write alias comments, if wanted.
-
-	if ( options & kXMP_WriteAliasComments ) {	// *** Hoist into a routine, used for Plain XMP also.
-
-		#if 0	// *** Buggy, disable for now.
-		
-		XMP_cAliasMapPos aliasPos = sRegisteredAliasMap->begin();
-		XMP_cAliasMapPos aliasEnd = sRegisteredAliasMap->end();
-		
-		for ( ; aliasPos != aliasEnd; ++aliasPos ) {
-
-			size_t nsPos = aliasPos->first.find ( schemaNode->value );
-			if ( nsPos == XMP_VarString::npos ) continue;
-			XMP_Assert ( nsPos == 0 );
-
-			for ( level = baseIndent+3; level > 0; --level ) outputStr += indentStr;
-
-			outputStr += "<!-- ";
-			outputStr += aliasPos->first;
-			outputStr += " is aliased to ";
-			for ( size_t step = 1, stepLim = aliasPos->second.size(); step != stepLim; ++step ) {
-				outputStr += aliasPos->second[step].step;
-			}
-			outputStr += " -->";
-			outputStr += newline;
-
-		}
-		
-		#endif
-
-	}
-	
-	// Write each of the schema's actual properties.
-	for ( size_t propNum = 0, propLim = schemaNode->children.size(); propNum < propLim; ++propNum ) {
-		const XMP_Node * currProp = schemaNode->children[propNum];
-		SerializePrettyRDFProperty ( currProp, outputStr, newline, indentStr, baseIndent+3 );
-	}
-	
-	// Write the rdf:Description end tag.
-	for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr;
-	outputStr += kRDF_SchemaEnd;
-	outputStr += newline;
-
-}	// SerializePrettyRDFSchema
-
-
-// -------------------------------------------------------------------------------------------------
-// SerializeCompactRDFAttrProps
-// ----------------------------
-//
-// Write each of the parent's simple unqualified properties as an attribute. Returns true if all
-// of the properties are written as attributes.
-
-static bool
-SerializeCompactRDFAttrProps ( const XMP_Node *	parentNode,
-							   XMP_VarString &	outputStr,
-							   XMP_StringPtr	newline,
-							   XMP_StringPtr	indentStr,
-							   XMP_Index		indent )
-{
-	size_t prop, propLim;
-	bool allAreAttrs = true;
-
-	for ( prop = 0, propLim = parentNode->children.size(); prop != propLim; ++prop ) {
-
-		const XMP_Node * currProp = parentNode->children[prop];
-		if ( ! CanBeRDFAttrProp ( currProp ) ) {
-			allAreAttrs = false;
-			continue;
-		}
-		
-		outputStr += newline;
-		for ( XMP_Index level = indent; level > 0; --level ) outputStr += indentStr;
-		outputStr += currProp->name;
-		outputStr += "=\"";
-		AppendNodeValue ( outputStr, currProp->value, kForAttribute );
-		outputStr += '"';
-
-	}
-	
-	return allAreAttrs;
-
-}	// SerializeCompactRDFAttrProps
-
-
-// -------------------------------------------------------------------------------------------------
-// SerializeCompactRDFElemProps
-// ----------------------------
-//
-// Recursively handles the "value" for a node that must be written as an RDF property element. It
-// does not matter if it is a top level property, a field of a struct, or an item of an array.  The
-// indent is that for the property element. The patterns bwlow ignore attribute qualifiers such as
-// xml:lang, they don't affect the output form.
-//
-//	<ns:UnqualifiedStructProperty-1
-//		... The fields as attributes, if all are simple and unqualified
-//	/>
-//
-//	<ns:UnqualifiedStructProperty-2 rdf:parseType="Resource">
-//		... The fields as elements, if none are simple and unqualified
-//	</ns:UnqualifiedStructProperty-2>
-//
-//	<ns:UnqualifiedStructProperty-3>
-//		<rdf:Description
-//			... The simple and unqualified fields as attributes
-//		>
-//			... The compound or qualified fields as elements
-//		</rdf:Description>
-//	</ns:UnqualifiedStructProperty-3>
-//
-//	<ns:UnqualifiedArrayProperty>
-//		<rdf:Bag> or Seq or Alt
-//			... Array items as rdf:li elements, same forms as top level properties
-//		</rdf:Bag>
-//	</ns:UnqualifiedArrayProperty>
-//
-//	<ns:QualifiedProperty rdf:parseType="Resource">
-//		<rdf:value> ... Property "value" following the unqualified forms ... </rdf:value>
-//		... Qualifiers looking like named struct fields
-//	</ns:QualifiedProperty>
-
-// *** Consider numbered array items, but has compatibility problems.
-// *** Consider qualified form with rdf:Description and attributes.
-
-static void
-SerializeCompactRDFElemProps ( const XMP_Node *	parentNode,
-							   XMP_VarString &	outputStr,
-							   XMP_StringPtr	newline,
-							   XMP_StringPtr	indentStr,
-							   XMP_Index		indent )
-{
-	XMP_Index level;
-
-	for ( size_t prop = 0, propLim = parentNode->children.size(); prop != propLim; ++prop ) {
-
-		const XMP_Node * propNode = parentNode->children[prop];
-		if ( CanBeRDFAttrProp ( propNode ) ) continue;
-
-		bool emitEndTag = true;
-		bool indentEndTag = true;
-
-		XMP_OptionBits propForm = propNode->options & kXMP_PropCompositeMask;
-
-		// -----------------------------------------------------------------------------------
-		// Determine the XML element name, write the name part of the start tag. Look over the
-		// qualifiers to decide on "normal" versus "rdf:value" form. Emit the attribute
-		// qualifiers at the same time.
-		
-		XMP_StringPtr elemName = propNode->name.c_str();
-		if ( *elemName == '[' ) elemName = "rdf:li";
-
-		for ( level = indent; level > 0; --level ) outputStr += indentStr;
-		outputStr += '<';
-		outputStr += elemName;
-
-		#define isCompact	false
-		bool hasGeneralQualifiers = isCompact;	// Might also become true later.
-		bool hasRDFResourceQual   = false;
-
-		for ( size_t qualNum = 0, qualLim = propNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
-			const XMP_Node * currQual = propNode->qualifiers[qualNum];
-			if ( ! IsRDFAttrQualifier ( currQual->name ) ) {
-				hasGeneralQualifiers = true;
-			} else {
-				if ( currQual->name == "rdf:resource" ) hasRDFResourceQual = true;
-				outputStr += ' ';
-				outputStr += currQual->name;
-				outputStr += "=\"";
-				AppendNodeValue ( outputStr, currQual->value, kForAttribute );
-				outputStr += '"';
-			}
-		}
-		
-		// --------------------------------------------------------
-		// Process the property according to the standard patterns.
-	
-		if ( hasGeneralQualifiers ) {
-		
-			// -------------------------------------------------------------------------------------
-			// The node has general qualifiers, ones that can't be attributes on a property element.
-			// Emit using the qualified property pseudo-struct form. The value is output by a call
-			// to SerializePrettyRDFProperty with emitAsRDFValue set.
-			
-			// *** We're losing compactness in the calls to SerializePrettyRDFProperty.
-			// *** Should refactor to have SerializeCompactRDFProperty that does one node.
-
-			outputStr += " rdf:parseType=\"Resource\">";
-			outputStr += newline;
-
-			SerializePrettyRDFProperty ( propNode, outputStr, newline, indentStr, indent+1, true );
-		
-			size_t qualNum = 0;
-			size_t qualLim = propNode->qualifiers.size();
-			if ( propNode->options & kXMP_PropHasLang ) ++qualNum;
-			
-			for ( ; qualNum < qualLim; ++qualNum ) {
-				const XMP_Node * currQual = propNode->qualifiers[qualNum];
-				SerializePrettyRDFProperty ( currQual, outputStr, newline, indentStr, indent+1 );
-			}
-			
-		} else {
-
-			// --------------------------------------------------------------------
-			// This node has only attribute qualifiers. Emit as a property element.
-			
-			if ( propForm == 0 ) {
-			
-				// --------------------------
-				// This is a simple property.
-				
-				if ( propNode->options & kXMP_PropValueIsURI ) {
-					outputStr += " rdf:resource=\"";
-					AppendNodeValue ( outputStr, propNode->value, kForAttribute );
-					outputStr += "\"/>";
-					outputStr += newline;
-					emitEndTag = false;
-				} else if ( propNode->value.empty() ) {
-					outputStr += "/>";
-					outputStr += newline;
-					emitEndTag = false;
-				} else {
-					outputStr += '>';
-					AppendNodeValue ( outputStr, propNode->value, kForElement );
-					indentEndTag = false;
-				}
-				
-			} else if ( propForm & kXMP_PropValueIsArray ) {
-
-				// -----------------
-				// This is an array.
-				
-				outputStr += '>';
-				outputStr += newline;
-				EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsStartTag );
-			
-				if ( XMP_ArrayIsAltText(propNode->options) ) NormalizeLangArray ( (XMP_Node*)propNode );
-				SerializeCompactRDFElemProps ( propNode, outputStr, newline, indentStr, indent+2 );
-
-				EmitRDFArrayTag ( propForm, outputStr, newline, indentStr, indent+1, propNode->children.size(), kIsEndTag );
-
-			} else {
-
-				// ----------------------
-				// This must be a struct.
-				
-				XMP_Assert ( propForm & kXMP_PropValueIsStruct );
-
-				bool hasAttrFields = false;
-				bool hasElemFields = false;
-			
-				size_t field, fieldLim;
-				for ( field = 0, fieldLim = propNode->children.size(); field != fieldLim; ++field ) {
-					XMP_Node * currField = propNode->children[field];
-					if ( CanBeRDFAttrProp ( currField ) ) {
-						hasAttrFields = true;
-						if ( hasElemFields ) break;	// No sense looking further.
-					} else {
-						hasElemFields = true;
-						if ( hasAttrFields ) break;	// No sense looking further.
-					}
-				}
-				
-				if ( hasRDFResourceQual && hasElemFields ) {
-					XMP_Throw ( "Can't mix rdf:resource qualifier and element fields", kXMPErr_BadRDF );
-				}
-				
-				if ( propNode->children.size() == 0 ) {
-				
-					// Catch an empty struct as a special case. The case below would emit an empty
-					// XML element, which gets reparsed as a simple property with an empty value.
-					outputStr += " rdf:parseType=\"Resource\"/>";
-					outputStr += newline;
-					emitEndTag = false;
-				
-				} else if ( ! hasElemFields ) {
-
-					// All fields can be attributes, use the emptyPropertyElt form.
-					SerializeCompactRDFAttrProps ( propNode, outputStr, newline, indentStr, indent+1 );
-					outputStr += "/>";
-					outputStr += newline;
-					emitEndTag = false;
-
-				} else if ( ! hasAttrFields ) {
-				
-					// All fields must be elements, use the parseTypeResourcePropertyElt form.
-					outputStr += " rdf:parseType=\"Resource\">";
-					outputStr += newline;
-					SerializeCompactRDFElemProps ( propNode, outputStr, newline, indentStr, indent+1 );
-				
-				} else {
-				
-					// Have a mix of attributes and elements, use an inner rdf:Description.
-					outputStr += '>';
-					outputStr += newline;
-					for ( level = indent+1; level > 0; --level ) outputStr += indentStr;
-					outputStr += "<rdf:Description";
-					SerializeCompactRDFAttrProps ( propNode, outputStr, newline, indentStr, indent+2 );
-					outputStr += ">";
-					outputStr += newline;
-					SerializeCompactRDFElemProps ( propNode, outputStr, newline, indentStr, indent+1 );
-					for ( level = indent+1; level > 0; --level ) outputStr += indentStr;
-					outputStr += kRDF_StructEnd;
-					outputStr += newline;
-
-				}
-
-			}
-
-		}
-		
-		// ----------------------------------
-		// Emit the property element end tag.
-		
-		if ( emitEndTag ) {
-			if ( indentEndTag ) for ( level = indent; level > 0; --level ) outputStr += indentStr;
-			outputStr += "</";
-			outputStr += elemName;
-			outputStr += '>';
-			outputStr += newline;
-		}
-
-	}
-	
-}	// SerializeCompactRDFElemProps
-
-
-// -------------------------------------------------------------------------------------------------
-// SerializeCompactRDFSchemas
-// --------------------------
-//
-// All properties from all schema are written in a single rdf:Description element, as are all of the
-// necessary namespace declarations. The baseIndent is the base level for the entire serialization,
-// that of the x:xmpmeta element. The x:xmpmeta and rdf:RDF elements have already been written.
-//
-// Top level simple unqualified properties are written as attributes of the (only) rdf:Description
-// element. Structs, arrays, and qualified properties are written by SerializeCompactRDFElemProp. An
-// xml:lang qualifier on a simple property prevents the attribute form.
-//
-//	<rdf:Description rdf:about="TreeName"
-//			xmlns:ns="URI" ...
-//		ns:UnqualifiedSimpleProperty="value" ... >
-//		... The remaining properties of the schema, see SerializeCompactRDFElemProps
-//	</rdf:Description>
-
-static void
-SerializeCompactRDFSchemas ( const XMP_Node & xmpTree,
-							 XMP_VarString &  outputStr,
-							 XMP_StringPtr	  newline,
-							 XMP_StringPtr	  indentStr,
-							 XMP_Index		  baseIndent )
-{
-	XMP_Index level;
-	size_t schema, schemaLim;
-	
-	// Begin the rdf:Description start tag.
-	for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr;
-	outputStr += kRDF_SchemaStart;
-	outputStr += '"';
-	outputStr += xmpTree.name;
-	outputStr += '"';
-	
-	// Write all necessary xmlns attributes.
-	
-	size_t totalLen = 8;	// Start at 8 for "xml:rdf:".
-	XMP_cStringMapPos currPos = sNamespacePrefixToURIMap->begin();
-	XMP_cStringMapPos endPos  = sNamespacePrefixToURIMap->end();
-	for ( ; currPos != endPos; ++currPos ) totalLen += currPos->first.size();
-
-	XMP_VarString usedNS;
-	usedNS.reserve ( totalLen );
-	usedNS = "xml:rdf:";
-
-	for ( schema = 0, schemaLim = xmpTree.children.size(); schema != schemaLim; ++schema ) {
-		const XMP_Node * currSchema = xmpTree.children[schema];
-		DeclareUsedNamespaces ( currSchema, usedNS, outputStr, newline, indentStr, baseIndent+4 );
-	}
-	
-	// Write the top level "attrProps" and close the rdf:Description start tag.
-	bool allAreAttrs = true;
-	for ( schema = 0, schemaLim = xmpTree.children.size(); schema != schemaLim; ++schema ) {
-		const XMP_Node * currSchema = xmpTree.children[schema];
-		allAreAttrs &= SerializeCompactRDFAttrProps ( currSchema, outputStr, newline, indentStr, baseIndent+3 );
-	}
-	if ( ! allAreAttrs ) {
-		outputStr += ">";
-		outputStr += newline;
-	} else {
-		outputStr += "/>";
-		outputStr += newline;
-		return;	// ! Done if all properties in all schema are written as attributes.
-	}
-
-	// Write the remaining properties for each schema.
-	for ( schema = 0, schemaLim = xmpTree.children.size(); schema != schemaLim; ++schema ) {
-		const XMP_Node * currSchema = xmpTree.children[schema];
-		SerializeCompactRDFElemProps ( currSchema, outputStr, newline, indentStr, baseIndent+3 );
-	}
-	
-	// Write the rdf:Description end tag.
-	// *** Elide the end tag if everything (all props in all schema) is an attr.
-	for ( level = baseIndent+2; level > 0; --level ) outputStr += indentStr;
-	outputStr += kRDF_SchemaEnd;
-	outputStr += newline;
-
-}	// SerializeCompactRDFSchemas
-
-
-// -------------------------------------------------------------------------------------------------
-// SerializeAsRDF
-// --------------
-//
-//	<?xpacket begin... ?>
-//	<x:xmpmeta xmlns:x=... >
-//		<rdf:RDF xmlns:rdf=... >
-//
-//			... The properties, see SerializePrettyRDFSchema or SerializeCompactRDFSchemas
-//
-//		</rdf:RDF>
-//	</x:xmpmeta>
-//	<?xpacket end... ?>
-
-// *** Need to strip empty arrays?
-// *** Option to strip/keep empty structs?
-// *** Need to verify handling of rdf:type qualifiers in pretty and compact.
-// *** Need to verify round tripping of rdf:ID and similar qualifiers, see RDF 7.2.21.
-// *** Check cases of rdf:resource plus explicit attr qualifiers (like xml:lang).
-
-static void
-SerializeAsRDF ( const XMPMeta & xmpObj,
-				 XMP_VarString & headStr,	// Everything up to the padding.
-				 XMP_VarString & tailStr,	// Everything after the padding.
-				 XMP_OptionBits	 options,
-				 XMP_StringPtr	 newline,
-				 XMP_StringPtr	 indentStr,
-				 XMP_Index		 baseIndent )
-{
-	const size_t treeNameLen = xmpObj.tree.name.size();
-	const size_t indentLen   = strlen ( indentStr );
-
-	// First estimate the worst case space and reserve room in the output string. This optimization
-	// avoids reallocating and copying the output as it grows. The initial count does not look at
-	// the values of properties, so it does not account for character entities, e.g. &#xA; for newline.
-	// Since there can be a lot of these in things like the base 64 encoding of a large thumbnail,
-	// inflate the count by 1/4 (easy to do) to accommodate.
-	
-	// *** Need to include estimate for alias comments.
-	
-	size_t outputLen = 2 * (strlen(kPacketHeader) + strlen(kRDF_XMPMetaStart) + strlen(kRDF_RDFStart) + 3*baseIndent*indentLen);
-	
-	for ( size_t schemaNum = 0, schemaLim = xmpObj.tree.children.size(); schemaNum < schemaLim; ++schemaNum ) {
-		const XMP_Node * currSchema = xmpObj.tree.children[schemaNum];
-		outputLen += 2*(baseIndent+2)*indentLen + strlen(kRDF_SchemaStart) + treeNameLen + strlen(kRDF_SchemaEnd) + 2;
-		outputLen += EstimateRDFSize ( currSchema, baseIndent+2, indentLen );
-	}
-	
-	outputLen += (outputLen >> 2);	// Inflate by 1/4, an empirical fudge factor.
-	
-	// Now generate the RDF into the head string as UTF-8.
-	
-	XMP_Index level;
-	
-	headStr.erase();
-	headStr.reserve ( outputLen );
-	
-	// Write the packet header PI.
-	if ( ! (options & kXMP_OmitPacketWrapper) ) {
-		for ( level = baseIndent; level > 0; --level ) headStr += indentStr;
-		headStr += kPacketHeader;
-		headStr += newline;
-	}
-
-	// Write the xmpmeta element's start tag.
-	if ( ! (options & kXMP_OmitXMPMetaElement) ) {
-		for ( level = baseIndent; level > 0; --level ) headStr += indentStr;
-		headStr += kRDF_XMPMetaStart;
-		headStr += kXMPCore_VersionMessage "\">";
-		headStr += newline;
-	}
-
-	// Write the rdf:RDF start tag.
-	for ( level = baseIndent+1; level > 0; --level ) headStr += indentStr;
-	headStr += kRDF_RDFStart;
-	headStr += newline;
-	
-	// Write all of the properties.
-	if ( options & kXMP_UseCompactFormat ) {
-		SerializeCompactRDFSchemas ( xmpObj.tree, headStr, newline, indentStr, baseIndent );
-	} else {
-		if ( xmpObj.tree.children.size() > 0 ) {
-			for ( size_t schemaNum = 0, schemaLim = xmpObj.tree.children.size(); schemaNum < schemaLim; ++schemaNum ) {
-				const XMP_Node * currSchema = xmpObj.tree.children[schemaNum];
-				SerializePrettyRDFSchema ( xmpObj.tree.name, currSchema, headStr, options, newline, indentStr, baseIndent );
-			}
-		} else {
-			for ( XMP_Index level = baseIndent+2; level > 0; --level ) headStr += indentStr;
-			headStr += kRDF_SchemaStart;	// Special case an empty XMP object.
-			headStr += '"';
-			headStr += xmpObj.tree.name;
-			headStr += "\"/>";
-			headStr += newline;
-		}
-	}
-
-	// Write the rdf:RDF end tag.
-	for ( level = baseIndent+1; level > 0; --level ) headStr += indentStr;
-	headStr += kRDF_RDFEnd;
-	headStr += newline;
-
-	// Write the xmpmeta end tag.
-	if ( ! (options & kXMP_OmitXMPMetaElement) ) {
-		for ( level = baseIndent; level > 0; --level ) headStr += indentStr;
-		headStr += kRDF_XMPMetaEnd;
-		headStr += newline;
-	}
-	
-	// Write the packet trailer PI into the tail string as UTF-8.
-	tailStr.erase();
-	if ( ! (options & kXMP_OmitPacketWrapper) ) {
-		tailStr.reserve ( strlen(kPacketTrailer) + (strlen(indentStr) * baseIndent) );
-		for ( level = baseIndent; level > 0; --level ) tailStr += indentStr;
-		tailStr += kPacketTrailer;
-		if ( options & kXMP_ReadOnlyPacket ) tailStr[tailStr.size()-4] = 'r';
-	}
-	
-	// ! This assert is just a performance check, to see if the reserve was enough.
-	// *** XMP_Assert ( headStr.size() <= outputLen );
-	// *** Don't use an assert. Think of some way to track this without risk of aborting the client.
-	
-}	// SerializeAsRDF
-
-// -------------------------------------------------------------------------------------------------
-// SerializeToBuffer
-// -----------------
-
-void
-XMPMeta::SerializeToBuffer ( XMP_StringPtr * rdfString,
-							 XMP_StringLen * rdfSize,
-							 XMP_OptionBits	 options,
-							 XMP_StringLen	 padding,
-							 XMP_StringPtr	 newline,
-							 XMP_StringPtr	 indentStr,
-							 XMP_Index		 baseIndent ) const
-{
-	XMP_Assert ( (rdfString != 0) && (rdfSize != 0) && (newline != 0) && (indentStr != 0) );
-
-	// Fix up some default parameters.
-	
-	enum { kDefaultPad = 2048 };
-	size_t unicodeUnitSize = 1;
-	XMP_OptionBits charEncoding = options & kXMP_EncodingMask;
-
-	if ( charEncoding != kXMP_EncodeUTF8 ) {
-		if ( options & _XMP_UTF16_Bit ) {
-			if ( options & _XMP_UTF32_Bit ) XMP_Throw ( "Can't use both _XMP_UTF16_Bit and _XMP_UTF32_Bit", kXMPErr_BadOptions );
-			unicodeUnitSize = 2;
-		} else if ( options & _XMP_UTF32_Bit ) {
-			unicodeUnitSize = 4;
-		} else {
-			XMP_Throw ( "Can't use _XMP_LittleEndian_Bit by itself", kXMPErr_BadOptions );
-		}
-	}
-	
-	if ( options & kXMP_OmitAllFormatting ) {
-		newline = " ";	// ! Yes, a space for "newline". This ensures token separation.
-		indentStr = "";
-	} else {
-		if ( *newline == 0 ) newline = "\xA";	// Linefeed
-		if ( *indentStr == 0 ) {
-			indentStr = " ";
-			if ( ! (options & kXMP_UseCompactFormat) ) indentStr  = "   ";
-		}
-	}
-	
-	if ( options & kXMP_ExactPacketLength ) {
-		if ( options & (kXMP_OmitPacketWrapper | kXMP_IncludeThumbnailPad) ) {
-			XMP_Throw ( "Inconsistent options for exact size serialize", kXMPErr_BadOptions );
-		}
-		if ( (padding & (unicodeUnitSize-1)) != 0 ) {
-			XMP_Throw ( "Exact size must be a multiple of the Unicode element", kXMPErr_BadOptions );
-		}
-	} else if ( options & kXMP_ReadOnlyPacket ) {
-		if ( options & (kXMP_OmitPacketWrapper | kXMP_IncludeThumbnailPad) ) {
-			XMP_Throw ( "Inconsistent options for read-only packet", kXMPErr_BadOptions );
-		}
-		padding = 0;
-	} else if ( options & kXMP_OmitPacketWrapper ) {
-		if ( options & kXMP_IncludeThumbnailPad ) {
-			XMP_Throw ( "Inconsistent options for non-packet serialize", kXMPErr_BadOptions );
-		}
-		padding = 0;
-	} else {
-		if ( padding == 0 ) padding = kDefaultPad * unicodeUnitSize;
-		if ( options & kXMP_IncludeThumbnailPad ) {
-			if ( ! this->DoesPropertyExist ( kXMP_NS_XMP, "Thumbnails" ) ) padding += (10000 * unicodeUnitSize);	// *** Need a better estimate.
-		}
-	}
-
-	// Serialize as UTF-8, then convert to UTF-16 or UTF-32 if necessary, and assemble with the padding and tail.
-	
-	std::string tailStr;
-
-	SerializeAsRDF ( *this, *sOutputStr, tailStr, options, newline, indentStr, baseIndent );
-	if ( charEncoding == kXMP_EncodeUTF8 ) {
-
-		if ( options & kXMP_ExactPacketLength ) {
-			size_t minSize = sOutputStr->size() + tailStr.size();
-			if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize );
-			padding -= minSize;	// Now the actual amount of padding to add.
-		}
-		
-		size_t newlineLen = strlen ( newline );
-	
-		if ( padding < newlineLen ) {
-			sOutputStr->append ( padding, ' ' );
-		} else {
-			padding -= newlineLen;	// Write this newline last.
-			while ( padding >= (100 + newlineLen) ) {
-				sOutputStr->append ( 100, ' ' );
-				*sOutputStr += newline;
-				padding -= (100 + newlineLen);
-			}
-			sOutputStr->append ( padding, ' ' );
-			*sOutputStr += newline;
-		}
-
-		*sOutputStr += tailStr;
-	
-	} else {
-	
-		// Need to convert the encoding. Swap the UTF-8 into a local string and convert back. Assemble everything.
-		
-		XMP_VarString utf8Str, newlineStr;
-		bool bigEndian = ((charEncoding & _XMP_LittleEndian_Bit) == 0);
-		
-		if ( charEncoding & _XMP_UTF16_Bit ) {
-
-			std::string padStr ( "  " );  padStr[0] = 0;	// Assume big endian.
-			
-			utf8Str.swap ( *sOutputStr );
-			ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), sOutputStr, bigEndian );
-			utf8Str.swap ( tailStr );
-			ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &tailStr, bigEndian );
-
-			if ( options & kXMP_ExactPacketLength ) {
-				size_t minSize = sOutputStr->size() + tailStr.size();
-				if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize );
-				padding -= minSize;	// Now the actual amount of padding to add (in bytes).
-			}
-
-			utf8Str.assign ( newline );
-			ToUTF16 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &newlineStr, bigEndian );
-			size_t newlineLen = newlineStr.size();
-	
-			if ( padding < newlineLen ) {
-				for ( int i = padding/2; i > 0; --i ) *sOutputStr += padStr;
-			} else {
-				padding -= newlineLen;	// Write this newline last.
-				while ( padding >= (200 + newlineLen) ) {
-					for ( int i = 100; i > 0; --i ) *sOutputStr += padStr;
-					*sOutputStr += newlineStr;
-					padding -= (200 + newlineLen);
-				}
-				for ( int i = padding/2; i > 0; --i ) *sOutputStr += padStr;
-				*sOutputStr += newlineStr;
-			}
-
-			*sOutputStr += tailStr;
-
-		} else {
-
-			std::string padStr ( "    " );  padStr[0] = padStr[1] = padStr[2] = 0;	// Assume big endian.
-//			UTF8_to_UTF32_Proc Converter = UTF8_to_UTF32BE;
-
-			if ( charEncoding & _XMP_LittleEndian_Bit ) {
-				padStr[0] = ' '; padStr[1] = padStr[2] = padStr[3] = 0;
-//				Converter = UTF8_to_UTF32LE;
-			}
-			
-			utf8Str.swap ( *sOutputStr );
-			ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), sOutputStr, bigEndian );
-			utf8Str.swap ( tailStr );
-			ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &tailStr, bigEndian );
-
-			if ( options & kXMP_ExactPacketLength ) {
-				size_t minSize = sOutputStr->size() + tailStr.size();
-				if ( minSize > padding ) XMP_Throw ( "Can't fit into specified packet size", kXMPErr_BadSerialize );
-				padding -= minSize;	// Now the actual amount of padding to add (in bytes).
-			}
-
-			utf8Str.assign ( newline );
-			ToUTF32 ( (UTF8Unit*)utf8Str.c_str(), utf8Str.size(), &newlineStr, bigEndian );
-			size_t newlineLen = newlineStr.size();
-	
-			if ( padding < newlineLen ) {
-				for ( int i = padding/4; i > 0; --i ) *sOutputStr += padStr;
-			} else {
-				padding -= newlineLen;	// Write this newline last.
-				while ( padding >= (400 + newlineLen) ) {
-					for ( int i = 100; i > 0; --i ) *sOutputStr += padStr;
-					*sOutputStr += newlineStr;
-					padding -= (400 + newlineLen);
-				}
-				for ( int i = padding/4; i > 0; --i ) *sOutputStr += padStr;
-				*sOutputStr += newlineStr;
-			}
-
-			*sOutputStr += tailStr;
-
-		}
-	
-	}
-
-	// Return the finished string.
-	
-	*rdfString = sOutputStr->c_str();
-	*rdfSize   = sOutputStr->size();
-
-}	// SerializeToBuffer
-
-// =================================================================================================
diff --git a/xmpsdk/src/XMPMeta.cpp b/xmpsdk/src/XMPMeta.cpp
deleted file mode 100644
index 2720cf25..00000000
--- a/xmpsdk/src/XMPMeta.cpp
+++ /dev/null
@@ -1,1649 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-//
-// Adobe patent application tracking #P435, entitled 'Unique markers to simplify embedding data of
-// one format in a file with a different format', inventors: Sean Parent, Greg Gilley.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-
-#include <stdio.h>
-
-#include "XMPMeta.hpp"
-#include "XMPIterator.hpp"
-#include "XMPUtils.hpp"
-#include "XMP_Version.h"
-#include "UnicodeInlines.incl_cpp"
-#include "UnicodeConversions.hpp"
-
-#include <algorithm>	// For sort and stable_sort.
-
-#if XMP_DebugBuild
-	#include <iostream>
-#endif
-
-using namespace std;
-
-#if XMP_WinBuild
-#ifdef _MSC_VER
-	#pragma warning ( disable : 4533 )	// initialization of '...' is skipped by 'goto ...'
-	#pragma warning ( disable : 4702 )	// unreachable code
-	#pragma warning ( disable : 4800 )	// forcing value to bool 'true' or 'false' (performance warning)
-	#pragma warning ( disable : 4996 )	// '...' was declared deprecated
-#endif
-#endif
-
-
-// *** Use the XMP_PropIsXyz (Schema, Simple, Struct, Array, ...) macros
-// *** Add debug codegen checks, e.g. that typical masking operations really work
-// *** Change all uses of strcmp and strncmp to XMP_LitMatch and XMP_LitNMatch
-
-
-// =================================================================================================
-// Local Types and Constants
-// =========================
-
-
-// =================================================================================================
-// Static Variables
-// ================
-
-XMP_VarString * xdefaultName = 0;
-
-// These are embedded version strings.
-
-const char * kXMPCore_EmbeddedVersion   = kXMPCore_VersionMessage;
-const char * kXMPCore_EmbeddedCopyright = kXMPCoreName " " kXMP_CopyrightStr;
-
-// =================================================================================================
-// Local Utilities
-// ===============
-
-#define IsHexDigit(ch)		( (('0' <= (ch)) && ((ch) <= '9')) || (('A' <= (ch)) && ((ch) <= 'F')) )
-#define HexDigitValue(ch)	( (((ch) - '0') < 10) ? ((ch) - '0') : ((ch) - 'A' + 10) )
-
-static const char * kTenSpaces = "          ";
-#define OutProcPadding(pad)	{ size_t padLen = (pad); 												\
-							  for ( ; padLen >= 10; padLen -= 10 ) OutProcNChars ( kTenSpaces, 10 );	\
-							  for ( ; padLen > 0; padLen -= 1 ) OutProcNChars ( " ", 1 ); }
-
-
-#define OutProcNewline()	{ status = (*outProc) ( refCon, "\n", 1 );  if ( status != 0 ) goto EXIT; }
-
-#define OutProcNChars(p,n)	{ status = (*outProc) ( refCon, (p), (n) );  if ( status != 0 ) goto EXIT; }
-
-#define OutProcLiteral(lit)	{ status = (*outProc) ( refCon, (lit), strlen(lit) );  if ( status != 0 ) goto EXIT; }
-
-#define OutProcString(str)	{ status = (*outProc) ( refCon, (str).c_str(), (str).size() );  if ( status != 0 ) goto EXIT; }
-
-#define OutProcULong(num)	{ snprintf ( buffer, sizeof(buffer), "%lu", (num) ); /* AUDIT: Using sizeof for snprintf length is safe */ \
-							  status = (*outProc) ( refCon, buffer, strlen(buffer) );  if ( status != 0 ) goto EXIT; }
-
-#define OutProcHexInt(num)	{ snprintf ( buffer, sizeof(buffer), "%lX", (num) ); /* AUDIT: Using sizeof for snprintf length is safe */	\
-							  status = (*outProc) ( refCon, buffer, strlen(buffer) );  if ( status != 0 ) goto EXIT; }
-
-#define OutProcHexByte(num)	{ snprintf ( buffer, sizeof(buffer), "%.2X", (num) ); /* AUDIT: Using sizeof for snprintf length is safe */	\
-							  status = (*outProc) ( refCon, buffer, strlen(buffer) );  if ( status != 0 ) goto EXIT; }
-
-static const char * kIndent = "   ";
-#define OutProcIndent(lev)	{ for ( size_t i = 0; i < (lev); ++i ) OutProcNChars ( kIndent, 3 ); }
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpClearString
-// ---------------
-
-static XMP_Status
-DumpClearString ( const XMP_VarString & value, XMP_TextOutputProc outProc, void * refCon )
-{
-
-	char buffer [20];
-	bool prevNormal;
-	XMP_Status status = 0;
-	
-	XMP_StringPtr spanStart, spanEnd;
-	XMP_StringPtr valueEnd = &value[0] + value.size();
-	
-	spanStart = &value[0];
-	while ( spanStart < valueEnd ) {
-	
-		// Output the next span of regular characters.
-		for ( spanEnd = spanStart; spanEnd < valueEnd; ++spanEnd ) {
-			if ( (unsigned char)(*spanEnd) > 0x7F ) break;
-			if ( (*spanEnd < 0x20) && (*spanEnd != kTab) && (*spanEnd != kLF) ) break;
-		}
-		if ( spanStart != spanEnd ) status = (*outProc) ( refCon,  spanStart, (spanEnd-spanStart) );
-		if ( status != 0 ) break;
-		spanStart = spanEnd;
-		
-		// Output the next span of irregular characters.
-		prevNormal = true;
-		for ( spanEnd = spanStart; spanEnd < valueEnd; ++spanEnd ) {
-			if ( ((0x20 <= *spanEnd) && ((unsigned char)(*spanEnd) <= 0x7F)) || (*spanEnd == kTab) || (*spanEnd == kLF) ) break;
-			char space = ' ';
-			if ( prevNormal ) space = '<';
-			status = (*outProc) ( refCon, &space, 1 );
-			if ( status != 0 ) break;
-			OutProcHexByte ( *spanEnd );
-			prevNormal = false;
-		}
-		if ( ! prevNormal ) {
-			status = (*outProc) ( refCon, ">", 1 );
-			if ( status != 0 ) return status;
-		}
-		spanStart = spanEnd;
-
-	}
-
-EXIT:	
-	return status;
-	
-}	// DumpClearString
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpStringMap
-// -------------
-
-static XMP_Status
-DumpStringMap ( const XMP_StringMap & map, XMP_StringPtr label, XMP_TextOutputProc outProc, void * refCon )
-{
-	XMP_Status			status;
-	XMP_cStringMapPos	currPos;
-	XMP_cStringMapPos	endPos = map.end();
-	
-	size_t maxLen = 0;
-	for ( currPos = map.begin(); currPos != endPos; ++currPos ) {
-		size_t currLen = currPos->first.size();
-		if ( currLen > maxLen ) maxLen = currLen;
-	}
-	
-	OutProcNewline();
-	OutProcLiteral ( label );
-	OutProcNewline();
-	
-	for ( currPos = map.begin(); currPos != endPos; ++currPos ) {
-		OutProcNChars ( "  ", 2 );
-		DumpClearString ( currPos->first, outProc, refCon );
-		OutProcPadding ( maxLen - currPos->first.size() );
-		OutProcNChars ( " => ", 4 );
-		DumpClearString ( currPos->second, outProc, refCon );
-		OutProcNewline();
-	}
-	
-EXIT:
-	return status;
-	
-}	// DumpStringMap
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpNodeOptions
-// ---------------
-
-static XMP_Status
-DumpNodeOptions	( XMP_OptionBits	 options,
-				  XMP_TextOutputProc outProc,
-				  void *			 refCon )
-{
-	XMP_Status	status;
-	char		buffer [32];	// Decimal of a 64 bit int is at most about 20 digits.
-
-	static const char * optNames[] = { " schema",		// 0x8000_0000
-									   " ?30",
-									   " ?29",
-									   " -COMMAS-",
-									   " ?27",			// 0x0800_0000
-									   " ?26",
-									   " ?25",
-									   " ?24",
-									   " ?23",			// 0x0080_0000
-									   " isStale",
-									   " isDerived",
-									   " isStable",
-									   " ?19",			// 0x0008_0000
-									   " isInternal",
-									   " hasAliases",
-									   " isAlias",
-									   " -AFTER-",		// 0x0000_8000
-									   " -BEFORE-",
-									   " isCompact",
-									   " isLangAlt",
-									   " isAlt",		// 0x0000_0800
-									   " isOrdered",
-									   " isArray",
-									   " isStruct",
-									   " hasType",		// 0x0000_0080
-									   " hasLang",
-									   " isQual",
-									   " hasQual",
-									   " ?3",			// 0x0000_0008
-									   " ?2",
-									   " URI",
-									   " ?0" };
-
-	if ( options == 0 ) {
-	
-		OutProcNChars ( "(0x0)", 5 );
-	
-	} else {
-	
-		OutProcNChars ( "(0x", 3 );
-		OutProcHexInt ( options );
-		OutProcNChars ( " :", 2 );
-
-		XMP_OptionBits mask = 0x80000000;
-		for ( int b = 0; b < 32; ++b ) {
-			if ( options & mask ) OutProcLiteral ( optNames[b] );
-			mask = mask >> 1;
-		}
-		OutProcNChars ( ")", 1 );
-	
-	}
-	
-EXIT:
-	return status;
-
-}	// DumpNodeOptions
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpPropertyTree
-// ----------------
-
-// *** Extract the validation code into a separate routine to call on exit in debug builds.
-
-static XMP_Status
-DumpPropertyTree ( const XMP_Node *	  currNode,
-				   int				  indent,
-				   size_t			  itemIndex,
-				   XMP_TextOutputProc outProc,
-				   void *			  refCon )
-{
-	XMP_Status	status;
-	char		buffer [32];	// Decimal of a 64 bit int is at most about 20 digits.
-
-	OutProcIndent ( (size_t)indent );
-	if ( itemIndex == 0 ) {
-		if ( currNode->options & kXMP_PropIsQualifier ) OutProcNChars ( "? ", 2 );
-		DumpClearString ( currNode->name, outProc, refCon );
-	} else {
-		OutProcNChars ( "[", 1 );
-		OutProcULong ( static_cast<unsigned long>(itemIndex) );
-		OutProcNChars ( "]", 1 );
-	}
-
-	if ( ! (currNode->options & kXMP_PropCompositeMask) ) {
-		OutProcNChars ( " = \"", 4 );
-		DumpClearString ( currNode->value, outProc, refCon );
-		OutProcNChars ( "\"", 1 );
-	}
-
-	if ( currNode->options != 0 ) {
-		OutProcNChars ( "  ", 2 );
-		status = DumpNodeOptions ( currNode->options, outProc, refCon );
-		if ( status != 0 ) goto EXIT;
-	}
-	
-	if ( currNode->options & kXMP_PropHasLang ) {
-		if ( currNode->qualifiers.empty() || (currNode->qualifiers[0]->name != "xml:lang") ) {
-			OutProcLiteral ( "  ** bad lang flag **" );
-		}
-	}
-	// *** Check rdf:type also.
-
-	if ( ! (currNode->options & kXMP_PropCompositeMask) ) {
-		if ( ! currNode->children.empty() ) OutProcLiteral ( "  ** bad children **" );
-	} else if ( currNode->options & kXMP_PropValueIsArray ) {
-		if ( currNode->options & kXMP_PropValueIsStruct ) OutProcLiteral ( "  ** bad comp flags **" );
-	} else if ( (currNode->options & kXMP_PropCompositeMask) != kXMP_PropValueIsStruct ) {
-		OutProcLiteral ( "  ** bad comp flags **" );
-	}
-
-	#if 0	// *** XMP_DebugBuild
-		if ( (currNode->_namePtr != currNode->name.c_str()) ||
-			 (currNode->_valuePtr != currNode->value.c_str()) ) OutProcLiteral ( "  ** bad debug string **" );
-	#endif
-	
-	OutProcNewline();
-	
-	for ( size_t qualNum = 0, qualLim = currNode->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
-
-		const XMP_Node * currQual = currNode->qualifiers[qualNum];
-
-		if ( currQual->parent != currNode ) OutProcLiteral ( "** bad parent link => " );
-		if ( currQual->name == kXMP_ArrayItemName ) OutProcLiteral ( "** bad qual name => " );
-		if ( ! (currQual->options & kXMP_PropIsQualifier) ) OutProcLiteral ( "** bad qual flag => " );
-		if ( currQual->name == "xml:lang" ) {
-			if ( (qualNum != 0) || (! (currNode->options & kXMP_PropHasLang)) ) OutProcLiteral ( "** bad lang qual => " );
-		}
-
-		status = DumpPropertyTree ( currQual, indent+2, 0, outProc, refCon );
-		if ( status != 0 ) goto EXIT;
-
-	}
-
-	for ( size_t childNum = 0, childLim = currNode->children.size(); childNum < childLim; ++childNum ) {
-
-		const XMP_Node * currChild = currNode->children[childNum];
-
-		if ( currChild->parent != currNode ) OutProcLiteral ( "** bad parent link => " );
-		if ( currChild->options & kXMP_PropIsQualifier ) OutProcLiteral ( "** bad qual flag => " );
-	
-		if ( currNode->options & kXMP_PropValueIsArray ) {
-			itemIndex = childNum+1;
-			if ( currChild->name != kXMP_ArrayItemName ) OutProcLiteral ( "** bad item name => " );
-		} else {
-			itemIndex = 0;
-			if ( currChild->name == kXMP_ArrayItemName ) OutProcLiteral ( "** bad field name => " );
-		}
-
-		status = DumpPropertyTree ( currChild, indent+1, itemIndex, outProc, refCon );
-		if ( status != 0 ) goto EXIT;
-
-	}
-	
-EXIT:
-	return status;
-
-}	// DumpPropertyTree
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpXMLTree
-// -----------
-
-#if DumpXMLParseTree
-
-static inline void PutHexByte ( FILE * log, unsigned char ch )
-{
-
-	fprintf ( log, "\\x" );
-	if ( ch < 0x10 ) {
-		fprintf ( log, "%c", kHexDigits[ch] );
-	} else {
-		fprintf ( log, "%c%c", kHexDigits[ch>>4], kHexDigits[ch&0xF] );
-	}
-	
-}	// PutHexByte
-
-// -------------------------------------------------------------------------------------------------
-
-static void PutClearString ( FILE * log, const std::string & str )
-{
-
-	for ( size_t i = 0; i != str.size(); ++i ) {
-		unsigned char ch = str[i];
-		if ( (0x20 <= ch) && (ch <= 0x7F) ) {
-			fprintf ( log, "%c", ch );
-		} else {
-			PutHexByte ( log, ch );
-		}
-	}
-
-}	// PutClearString
-
-// -------------------------------------------------------------------------------------------------
-
-static void DumpXMLTree ( FILE * log, const XML_Node & node, int indent )
-{
-	size_t i;
-	
-	#if 0	// *** XMP_DebugBuild
-		if ( (node._namePtr != node.name.c_str()) ||
-			 (node._valuePtr != node.value.c_str()) ) fprintf ( log, "*** bad debug string ***\n" );
-	#endif
-	
-	for ( i = 0; i != (size_t)indent; ++i ) fprintf ( log, "  " );
-	
-	switch ( node.kind ) {
-	
-		case kRootNode :
-			fprintf ( log, "\nStart of XML tree dump\n\n" );
-			if ( (indent != 0) || (! node.attrs.empty()) ||
-				 (! node.ns.empty()) || (! node.name.empty()) || (!node.value.empty()) ) fprintf ( log, " ** invalid root ** \n" );
-			for ( i = 0; i < node.children.size(); ++i ) {
-				XMP_Uns8 kind = node.children[i]->kind;
-				if ( (kind == kRootNode) || (kind == kAttrNode) ) fprintf ( log, " ** invalid child ** \n" );
-				DumpXMLTree ( log, *node.children[i], indent+1 );
-			}
-			fprintf ( log, "\nEnd of XML tree dump\n" );
-			break;
-	
-		case kElemNode :
-			fprintf ( log, "Elem %s", node.name.c_str() );
-			if ( indent == 0 ) fprintf ( log, " ** invalid elem ** " );
-			if ( ! node.ns.empty() ) fprintf ( log, " @ %s", node.ns.c_str() );
-			fprintf ( log, "\n" );
-			for ( i = 0; i < node.attrs.size(); ++i ) {
-				XMP_Uns8 kind = node.attrs[i]->kind;
-				if ( kind != kAttrNode ) fprintf ( log, " ** invalid attr ** \n" );
-				DumpXMLTree ( log, *node.attrs[i], indent+2 );
-			}
-			for ( i = 0; i < node.children.size(); ++i ) {
-				XMP_Uns8 kind = node.children[i]->kind;
-				if ( (kind == kRootNode) || (kind == kAttrNode) ) fprintf ( log, " ** invalid child ** \n" );
-				DumpXMLTree ( log, *node.children[i], indent+1 );
-			}
-			break;
-	
-		case kAttrNode :
-			fprintf ( log, "Attr %s", node.name.c_str() );
-			if ( (indent == 0) || node.name.empty() || (! node.attrs.empty()) || (! node.children.empty()) ) fprintf ( log, " ** invalid attr ** " );
-			fprintf ( log, " = \"" );
-			PutClearString ( log, node.value );
-			fprintf ( log, "\"" );
-			if ( ! node.ns.empty() ) fprintf ( log, " @ %s", node.ns.c_str() );
-			fprintf ( log, "\n" );
-			break;
-	
-		case kCDataNode :
-			if ( (indent == 0) || (! node.ns.empty()) || (! node.name.empty()) ||
-				 (! node.attrs.empty()) || (! node.children.empty()) ) fprintf ( log, " ** invalid cdata ** \n" );
-			fprintf ( log, "\"" );
-			PutClearString ( log, node.value );
-			fprintf ( log, "\"\n" );
-			break;
-	
-		case kPINode :
-			fprintf ( log, "PI %s", node.name.c_str() );
-			if ( (indent == 0) || node.name.empty() || (! node.children.empty()) ) fprintf ( log, " ** invalid pi ** \n" );
-			if ( ! node.value.empty() ) {
-				fprintf ( log, " <? " );
-				PutClearString ( log, node.value );
-				fprintf ( log, " ?>" );
-			}
-			fprintf ( log, "\n" );
-			break;
-	
-	}
-
-}	// DumpXMLTree
-
-#endif	// DumpXMLParseTree
-
-
-// -------------------------------------------------------------------------------------------------
-// CompareNodeNames
-// ----------------
-//
-// Comparison routine for sorting XMP nodes by name. The name "xml:lang" is less than anything else,
-// and "rdf:type" is less than anything except "xml:lang". This preserves special rules for qualifiers.
-
-static bool
-CompareNodeNames ( XMP_Node * left, XMP_Node * right )
-{
-
-	if ( left->name  == "xml:lang" ) return true;
-	if ( right->name == "xml:lang" ) return false;
-	
-	if ( left->name  == "rdf:type" ) return true;
-	if ( right->name == "rdf:type" ) return false;
-	
-	return ( left->name < right->name );
-	
-}	// CompareNodeNames
-
-
-// -------------------------------------------------------------------------------------------------
-// CompareNodeValues
-// -----------------
-//
-// Comparison routine for sorting XMP nodes by value.
-
-static bool
-CompareNodeValues ( XMP_Node * left, XMP_Node * right )
-{
-
-	if ( XMP_PropIsSimple ( left->options ) && XMP_PropIsSimple ( right->options ) ) {
-		return ( left->value < right->value );
-	}
-
-	XMP_OptionBits leftForm  = left->options & kXMP_PropCompositeMask;
-	XMP_OptionBits rightForm = right->options & kXMP_PropCompositeMask;
-	
-	return ( leftForm < rightForm );
-	
-}	// CompareNodeValues
-
-
-// -------------------------------------------------------------------------------------------------
-// CompareNodeLangs
-// ----------------
-//
-// Comparison routine for sorting XMP nodes by xml:lang qualifier. An "x-default" value is less than
-// any other language.
-
-static bool
-CompareNodeLangs ( XMP_Node * left, XMP_Node * right )
-{
-
-	if ( left->qualifiers.empty()  || (left->qualifiers[0]->name  != "xml:lang") ) return false;
-	if ( right->qualifiers.empty() || (right->qualifiers[0]->name != "xml:lang") ) return false;
-	
-	if ( left->qualifiers[0]->value  == "x-default" ) return true;
-	if ( right->qualifiers[0]->value == "x-default" ) return false;
-	
-	return ( left->qualifiers[0]->value < right->qualifiers[0]->value );
-	
-}	// CompareNodeLangs
-
-
-// -------------------------------------------------------------------------------------------------
-// SortWithinOffspring
-// -------------------
-//
-// Sort one level down, within the elements of a node vector. This sorts the qualifiers of each
-// node. If the node is a struct it sorts the fields by names. If the node is an unordered array it
-// sorts the elements by value. If the node is an AltText array it sorts the elements by language.
-
-static void
-SortWithinOffspring ( XMP_NodeOffspring & nodeVec )
-{
-
-	for ( size_t i = 0, limit = nodeVec.size(); i < limit; ++i ) {
-	
-		XMP_Node * currPos = nodeVec[i];
-	
-		if ( ! currPos->qualifiers.empty() ) {
-			sort ( currPos->qualifiers.begin(), currPos->qualifiers.end(), CompareNodeNames );
-			SortWithinOffspring ( currPos->qualifiers );
-		}
-		
-		if ( ! currPos->children.empty() ) {
-
-			if ( XMP_PropIsStruct ( currPos->options ) || XMP_NodeIsSchema ( currPos->options ) ) {
-				sort ( currPos->children.begin(), currPos->children.end(), CompareNodeNames );
-			} else if ( XMP_PropIsArray ( currPos->options ) ) {
-				if ( XMP_ArrayIsUnordered ( currPos->options ) ) {
-					stable_sort ( currPos->children.begin(), currPos->children.end(), CompareNodeValues );
-				} else if ( XMP_ArrayIsAltText ( currPos->options ) ) {
-					sort ( currPos->children.begin(), currPos->children.end(), CompareNodeLangs );
-				}
-			}
-
-			SortWithinOffspring ( currPos->children );
-			
-		}
-
-	}
-	
-}	// SortWithinOffspring
-
-
-// =================================================================================================
-// Constructors
-// ============
-
-
-XMPMeta::XMPMeta() : clientRefs(0), prevTkVer(0), tree(XMP_Node(0,"",0)), xmlParser(0)
-{
-	// Nothing more to do, clientRefs is incremented in wrapper.
-	#if XMP_TraceCTorDTor
-		printf ( "Default construct XMPMeta @ %.8X\n", this );
-	#endif
-}	// XMPMeta
-
-// -------------------------------------------------------------------------------------------------
-
-XMPMeta::~XMPMeta() RELEASE_NO_THROW
-{
-	#if XMP_TraceCTorDTor
-		printf ( "Destruct XMPMeta @ %.8X\n", this );
-	#endif
-
-	XMP_Assert ( this->clientRefs <= 0 );
-	if ( xmlParser != 0 ) delete ( xmlParser );
-	xmlParser = 0;
-
-}	// ~XMPMeta
-
-
-// =================================================================================================
-// Class Static Functions
-// ======================
-//
-//
-// =================================================================================================
-
-// -------------------------------------------------------------------------------------------------
-// GetVersionInfo
-// --------------
-
-/* class-static */ void
-XMPMeta::GetVersionInfo ( XMP_VersionInfo * info )
-{
-
-	memset ( info, 0, sizeof(*info) );	// AUDIT: Safe, using sizeof the destination.
-	XMP_Assert ( sizeof(*info) == sizeof(XMP_VersionInfo) );
-	
-	info->major   = XMP_API_VERSION_MAJOR;
-	info->minor   = XMP_API_VERSION_MINOR;
-	info->micro   = XMP_API_VERSION_MICRO;
-	info->isDebug = kXMPCore_DebugFlag;
-	info->flags   = 0;	// ! None defined yet.
-	info->message = kXMPCore_VersionMessage;
-	
-}	// GetVersionInfo
-
-// -------------------------------------------------------------------------------------------------
-// Initialize
-// ----------
-
-/* class-static */ bool
-XMPMeta::Initialize()
-{
-	// Allocate and initialize static objects.
-	
-	++sXMP_InitCount;
-	if ( sXMP_InitCount > 1 ) return true;
-	
-	#if TraceXMPCalls
-		// xmpOut = fopen ( "xmp.out", "w" );	// Coordinate with client glue in WXMP_Common.hpp
-		fprintf ( xmpOut, "XMP initializing\n" ); fflush ( xmpOut );
-	#endif
-	
-	sExceptionMessage = new XMP_VarString();
-	XMP_InitMutex ( &sXMPCoreLock );
-    sOutputNS  = new XMP_VarString;
-    sOutputStr = new XMP_VarString;
-
-	xdefaultName = new XMP_VarString ( "x-default" );
-	
-	sNamespaceURIToPrefixMap	= new XMP_StringMap;
-	sNamespacePrefixToURIMap	= new XMP_StringMap;
-	sRegisteredAliasMap			= new XMP_AliasMap;
-	
-	InitializeUnicodeConversions();
-	
-	// Register standard namespaces and aliases.
-	RegisterNamespace ( kXMP_NS_XML, "xml" );
-	RegisterNamespace ( kXMP_NS_RDF, "rdf" );
-	RegisterNamespace ( kXMP_NS_DC, "dc" );
-
-	RegisterNamespace ( kXMP_NS_XMP, "xmp" );
-	RegisterNamespace ( kXMP_NS_PDF, "pdf" );
-	RegisterNamespace ( kXMP_NS_Photoshop, "photoshop" );
-	RegisterNamespace ( kXMP_NS_PSAlbum, "album" );
-	RegisterNamespace ( kXMP_NS_EXIF, "exif" );
-	RegisterNamespace ( kXMP_NS_EXIF_Aux, "aux" );
-	RegisterNamespace ( kXMP_NS_TIFF, "tiff" );
-	RegisterNamespace ( kXMP_NS_PNG, "png" );
-	RegisterNamespace ( kXMP_NS_JPEG, "jpeg" );
-	RegisterNamespace ( kXMP_NS_JP2K, "jp2k" );
-	RegisterNamespace ( kXMP_NS_CameraRaw, "crs" );
-	RegisterNamespace ( kXMP_NS_ASF, "asf" );
-	RegisterNamespace ( kXMP_NS_WAV, "wav" );
-
-	RegisterNamespace ( kXMP_NS_AdobeStockPhoto, "bmsp" );
-	RegisterNamespace ( kXMP_NS_CreatorAtom, "creatorAtom" );
-
-	RegisterNamespace ( kXMP_NS_XMP_Rights, "xmpRights" );
-	RegisterNamespace ( kXMP_NS_XMP_MM, "xmpMM" );
-	RegisterNamespace ( kXMP_NS_XMP_BJ, "xmpBJ" );
-	RegisterNamespace ( kXMP_NS_XMP_Note, "xmpNote" );
-
-	RegisterNamespace ( kXMP_NS_DM, "xmpDM" );
-	RegisterNamespace ( kXMP_NS_XMP_Text, "xmpT" );
-	RegisterNamespace ( kXMP_NS_XMP_PagedFile, "xmpTPg" );
-	RegisterNamespace ( kXMP_NS_XMP_Graphics, "xmpG" );
-	RegisterNamespace ( kXMP_NS_XMP_Image, "xmpGImg" );
-
-	RegisterNamespace ( kXMP_NS_XMP_Font, "stFnt" );
-	RegisterNamespace ( kXMP_NS_XMP_Dimensions, "stDim" );
-	RegisterNamespace ( kXMP_NS_XMP_ResourceEvent, "stEvt" );
-	RegisterNamespace ( kXMP_NS_XMP_ResourceRef, "stRef" );
-	RegisterNamespace ( kXMP_NS_XMP_ST_Version, "stVer" );
-	RegisterNamespace ( kXMP_NS_XMP_ST_Job, "stJob" );
-	RegisterNamespace ( kXMP_NS_XMP_ManifestItem, "stMfs" );
-
-	RegisterNamespace ( kXMP_NS_XMP_IdentifierQual, "xmpidq" );
-
-	RegisterNamespace ( kXMP_NS_IPTCCore, "Iptc4xmpCore" );
-	RegisterNamespace ( kXMP_NS_DICOM, "DICOM" );
-
-	RegisterNamespace ( kXMP_NS_PDFA_Schema, "pdfaSchema" );
-	RegisterNamespace ( kXMP_NS_PDFA_Property, "pdfaProperty" );
-	RegisterNamespace ( kXMP_NS_PDFA_Type, "pdfaType" );
-	RegisterNamespace ( kXMP_NS_PDFA_Field, "pdfaField" );
-	RegisterNamespace ( kXMP_NS_PDFA_ID, "pdfaid" );
-	RegisterNamespace ( kXMP_NS_PDFA_Extension, "pdfaExtension" );
-
-	RegisterNamespace ( kXMP_NS_PDFX, "pdfx" );
-	RegisterNamespace ( kXMP_NS_PDFX_ID, "pdfxid" );
-	
-	RegisterNamespace ( "adobe:ns:meta/", "x" );
-	RegisterNamespace ( "http://ns.adobe.com/iX/1.0/", "iX" );
-
-// 06-Oct-07, ahu: Do not use aliases. They result in unexpected behaviour.
-//	XMPMeta::RegisterStandardAliases ( "" );
-	
-	// Initialize the other core classes.
-	
-	if ( ! XMPIterator::Initialize() ) XMP_Throw ( "Failure from XMPIterator::Initialize", kXMPErr_InternalFailure );
-	if ( ! XMPUtils::Initialize() ) XMP_Throw ( "Failure from XMPUtils::Initialize", kXMPErr_InternalFailure );
-	// Do miscelaneous semantic checks of types and arithmetic.
-
-	XMP_Assert ( sizeof(XMP_Int8) == 1 );
-	XMP_Assert ( sizeof(XMP_Int16) == 2 );
-	XMP_Assert ( sizeof(XMP_Int32) == 4 );
-	XMP_Assert ( sizeof(XMP_Int64) == 8 );
-	XMP_Assert ( sizeof(XMP_Uns8) == 1 );
-	XMP_Assert ( sizeof(XMP_Uns16) == 2 );
-	XMP_Assert ( sizeof(XMP_Uns32) == 4 );
-	XMP_Assert ( sizeof(XMP_Uns64) == 8 );
-	
-	XMP_Assert ( sizeof(XMP_OptionBits) == 4 );	// Check that option masking work on all 32 bits.
-	XMP_OptionBits flag = ~0UL;
-
-	XMP_Assert ( flag == (XMP_OptionBits)(-1L) );
-	XMP_Assert ( (flag ^ kXMP_PropHasLang) == 0xFFFFFFBFUL );
-	XMP_Assert ( (flag & ~kXMP_PropHasLang) == 0xFFFFFFBFUL );
-	
-	XMP_OptionBits opt1 = 0;	// Check the general option bit macros.
-	XMP_OptionBits opt2 = flag;
-	XMP_SetOption ( opt1, kXMP_PropValueIsArray );
-	XMP_ClearOption ( opt2, kXMP_PropValueIsArray );
-	XMP_Assert ( opt1 == ~opt2 );
-	XMP_Assert ( XMP_TestOption ( opt1, kXMP_PropValueIsArray ) );
-	XMP_Assert ( ! XMP_TestOption ( opt2, kXMP_PropValueIsArray ) );
-	
-	XMP_Assert ( XMP_PropIsSimple ( ~kXMP_PropCompositeMask ) );	// Check the special option bit macros.
-	XMP_Assert ( ! XMP_PropIsSimple ( kXMP_PropValueIsStruct ) );
-	XMP_Assert ( ! XMP_PropIsSimple ( kXMP_PropValueIsArray ) );
-
-	XMP_Assert ( XMP_PropIsStruct ( kXMP_PropValueIsStruct ) );
-	XMP_Assert ( XMP_PropIsArray  ( kXMP_PropValueIsArray ) );
-	XMP_Assert ( ! XMP_PropIsStruct ( ~kXMP_PropValueIsStruct ) );
-	XMP_Assert ( ! XMP_PropIsArray  ( ~kXMP_PropValueIsArray ) );
-	
-	XMP_Assert ( XMP_ArrayIsUnordered ( ~kXMP_PropArrayIsOrdered ) );
-	XMP_Assert ( XMP_ArrayIsOrdered   ( kXMP_PropArrayIsOrdered ) );
-	XMP_Assert ( XMP_ArrayIsAlternate ( kXMP_PropArrayIsAlternate ) );
-	XMP_Assert ( XMP_ArrayIsAltText   ( kXMP_PropArrayIsAltText ) );
-	XMP_Assert ( ! XMP_ArrayIsUnordered ( kXMP_PropArrayIsOrdered ) );
-	XMP_Assert ( ! XMP_ArrayIsOrdered   ( ~kXMP_PropArrayIsOrdered ) );
-	XMP_Assert ( ! XMP_ArrayIsAlternate ( ~kXMP_PropArrayIsAlternate ) );
-	XMP_Assert ( ! XMP_ArrayIsAltText   ( ~kXMP_PropArrayIsAltText ) );
-	
-	XMP_Assert ( XMP_PropHasQualifiers ( kXMP_PropHasQualifiers ) );
-	XMP_Assert ( XMP_PropIsQualifier   ( kXMP_PropIsQualifier ) );
-	XMP_Assert ( XMP_PropHasLang       ( kXMP_PropHasLang ) );
-	XMP_Assert ( ! XMP_PropHasQualifiers ( ~kXMP_PropHasQualifiers ) );
-	XMP_Assert ( ! XMP_PropIsQualifier   ( ~kXMP_PropIsQualifier ) );
-	XMP_Assert ( ! XMP_PropHasLang       ( ~kXMP_PropHasLang ) );
-	
-	XMP_Assert ( XMP_NodeIsSchema ( kXMP_SchemaNode ) );
-	XMP_Assert ( XMP_PropIsAlias  ( kXMP_PropIsAlias ) );
-	XMP_Assert ( ! XMP_NodeIsSchema ( ~kXMP_SchemaNode ) );
-	XMP_Assert ( ! XMP_PropIsAlias  ( ~kXMP_PropIsAlias ) );
-	
-	#if 0	// Generally off, enable to hand check generated code.
-		extern XMP_OptionBits opt3, opt4;
-		if ( XMP_TestOption ( opt3, kXMP_PropValueIsArray ) ) opt4 = opt3;
-		if ( ! XMP_TestOption ( opt3, kXMP_PropValueIsStruct ) ) opt4 = opt3;
-		static bool ok1 = XMP_TestOption ( opt4, kXMP_PropValueIsArray );
-		static bool ok2 = ! XMP_TestOption ( opt4, kXMP_PropValueIsStruct );
-	#endif
-	
-	// Make sure the embedded info strings are referenced and kept.
-	if ( (kXMPCore_EmbeddedVersion[0] == 0) || (kXMPCore_EmbeddedCopyright[0] == 0) ) return false;
-	return true;
-
-}	// Initialize
-
-
-// -------------------------------------------------------------------------------------------------
-// Terminate
-// ---------
-
-#define EliminateGlobal(g) delete ( g ); g = 0
-
-/* class-static */ void
-XMPMeta::Terminate() RELEASE_NO_THROW
-{
-	--sXMP_InitCount;
-	if ( sXMP_InitCount > 0 ) return;
-
-	#if TraceXMPCalls
-		fprintf ( xmpOut, "XMP terminating\n" ); fflush ( xmpOut );
-		// fclose ( xmpOut );	// Coordinate with fopen in XMPMeta::Initialize.
-	#endif
-	
-	XMPIterator::Terminate();
-	XMPUtils::Terminate();
-	EliminateGlobal ( sNamespaceURIToPrefixMap );
-	EliminateGlobal ( sNamespacePrefixToURIMap );
-	EliminateGlobal ( sRegisteredAliasMap );
-    
-    EliminateGlobal ( xdefaultName );
-    EliminateGlobal ( sOutputNS );
-    EliminateGlobal ( sOutputStr );
-	EliminateGlobal ( sExceptionMessage );
-
-	XMP_TermMutex ( sXMPCoreLock );
-	
-}	// Terminate
-
-
-// -------------------------------------------------------------------------------------------------
-// Unlock
-// ------
-
-/* class-static */ void
-XMPMeta::Unlock ( XMP_OptionBits options )
-{
-	UNUSED(options);
-
-    #if TraceXMPLocking
-    	fprintf ( xmpOut, "  Unlocking XMP toolkit, count = %d\n", sLockCount ); fflush ( xmpOut );
-	#endif
-    --sLockCount;
-    XMP_Assert ( sLockCount == 0 );
-	XMP_ExitCriticalRegion ( sXMPCoreLock );
-
-}	// Unlock
-
-
-// -------------------------------------------------------------------------------------------------
-// UnlockObject
-// ------------
-
-void
-XMPMeta::UnlockObject ( XMP_OptionBits options ) const
-{
-	UNUSED(options);
-
-	XMPMeta::Unlock ( 0 );
-
-}	// UnlockObject
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpNamespaces
-// --------------
-//
-// Dump the prefix to URI map (easier to read) and verify that both are consistent and legit.
-
-// *** Should put checks in a separate routine for regular calling in debug builds.
-
-/* class-static */ XMP_Status
-XMPMeta::DumpNamespaces ( XMP_TextOutputProc outProc,
-                          void *             refCon )
-{
-	XMP_Assert ( outProc != 0 );	// ! Enforced by wrapper.
-	XMP_Status status = 0;
-	
-	XMP_StringMapPos p2uEnd = sNamespacePrefixToURIMap->end();	// ! Move up to avoid gcc complaints.
-	XMP_StringMapPos u2pEnd = sNamespaceURIToPrefixMap->end();
-	
-	status = DumpStringMap ( *sNamespacePrefixToURIMap, "Dumping namespace prefix to URI map", outProc, refCon );
-	if ( status != 0 ) goto EXIT;
-	
-	if ( sNamespacePrefixToURIMap->size() != sNamespaceURIToPrefixMap->size() ) {
-		OutProcLiteral ( "** bad namespace map sizes **" );
-		XMP_Throw ( "Fatal namespace map problem", kXMPErr_InternalFailure );
-	}
-	
-	for ( XMP_StringMapPos nsLeft = sNamespacePrefixToURIMap->begin(); nsLeft != p2uEnd; ++nsLeft ) {
-
-		XMP_StringMapPos nsOther = sNamespaceURIToPrefixMap->find ( nsLeft->second );
-		if ( (nsOther == u2pEnd) || (nsLeft != sNamespacePrefixToURIMap->find ( nsOther->second )) ) {
-			OutProcLiteral ( "  ** bad namespace URI **  " );
-			DumpClearString ( nsLeft->second, outProc, refCon );
-			goto FAILURE;
-		}
-		
-		for ( XMP_StringMapPos nsRight = nsLeft; nsRight != p2uEnd; ++nsRight ) {
-			if ( nsRight == nsLeft ) continue;	// ! Can't start at nsLeft+1, no operator+!
-			if ( nsLeft->second == nsRight->second ) {
-				OutProcLiteral ( "  ** duplicate namespace URI **  " );
-				DumpClearString ( nsLeft->second, outProc, refCon );
-				goto FAILURE;
-			}
-		}
-
-	}
-	
-	for ( XMP_StringMapPos nsLeft = sNamespaceURIToPrefixMap->begin(); nsLeft != u2pEnd; ++nsLeft ) {
-
-		XMP_StringMapPos nsOther = sNamespacePrefixToURIMap->find ( nsLeft->second );
-		if ( (nsOther == p2uEnd) || (nsLeft != sNamespaceURIToPrefixMap->find ( nsOther->second )) ) {
-			OutProcLiteral ( "  ** bad namespace prefix **  " );
-			DumpClearString ( nsLeft->second, outProc, refCon );
-			goto FAILURE;
-		}
-
-		for ( XMP_StringMapPos nsRight = nsLeft; nsRight != u2pEnd; ++nsRight ) {
-			if ( nsRight == nsLeft ) continue;	// ! Can't start at nsLeft+1, no operator+!
-			if ( nsLeft->second == nsRight->second ) {
-				OutProcLiteral ( "  ** duplicate namespace prefix **  " );
-				DumpClearString ( nsLeft->second, outProc, refCon );
-				goto FAILURE;
-			}
-		}
-
-	}
-
-EXIT:
-	return status;
-
-FAILURE:
-	OutProcNewline();
-	(void) DumpStringMap ( *sNamespaceURIToPrefixMap, "Dumping namespace URI to prefix map", outProc, refCon );
-	XMP_Throw ( "Fatal namespace map problem", kXMPErr_InternalFailure );
-	return 0;
-	
-}	// DumpNamespaces
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpAliases
-// -----------
-
-/* class-static */ XMP_Status
-XMPMeta::DumpAliases ( XMP_TextOutputProc outProc,
-                       void *             refCon )
-{
-	XMP_Assert ( outProc != 0 );	// ! Enforced by wrapper.
-	XMP_Status status = 0;
-
-	XMP_Assert ( sRegisteredAliasMap != 0 );
-
-	XMP_cAliasMapPos aliasPos;
-	XMP_cAliasMapPos aliasEnd = sRegisteredAliasMap->end();
-	
-	size_t maxLen = 0;
-	for ( aliasPos = sRegisteredAliasMap->begin(); aliasPos != aliasEnd; ++aliasPos ) {
-		size_t currLen = aliasPos->first.size();
-		if ( currLen > maxLen ) maxLen = currLen;
-	}
-	
-	OutProcLiteral ( "Dumping alias name to actual path map" );
-	OutProcNewline();
-		
-	for ( aliasPos = sRegisteredAliasMap->begin(); aliasPos != aliasEnd; ++aliasPos ) {
-
-		OutProcNChars ( "   ", 3 );
-		DumpClearString ( aliasPos->first, outProc, refCon );
-		OutProcPadding ( maxLen - aliasPos->first.size() );
-		OutProcNChars ( " => ", 4 );
-
-		size_t actualPathSize = aliasPos->second.size();
-		for ( size_t stepNum = 1; stepNum < actualPathSize; ++stepNum ) OutProcString ( aliasPos->second[stepNum].step );
-
-		XMP_OptionBits arrayForm = aliasPos->second[1].options & kXMP_PropArrayFormMask;
-
-		if ( arrayForm == 0 ) {
-			if ( actualPathSize != 2 ) OutProcLiteral ( "  ** bad actual path **" );
-		} else {
-			OutProcNChars ( "  ", 2 );
-			DumpNodeOptions ( arrayForm, outProc, refCon );
-			if ( ! (arrayForm & kXMP_PropValueIsArray) ) OutProcLiteral ( "  ** bad array form **" );
-			if ( actualPathSize != 3 ) OutProcLiteral ( "  ** bad actual path **" );
-		}
-
-		if ( aliasPos->second[0].options != kXMP_SchemaNode ) OutProcLiteral ( "  ** bad schema form **" );
-
-		OutProcNewline();
-
-	}
-	
-EXIT:
-	return status;
-	
-}	// DumpAliases
-
-
-// -------------------------------------------------------------------------------------------------
-// GetGlobalOptions
-// ----------------
-
-/* class-static */ XMP_OptionBits
-XMPMeta::GetGlobalOptions()
-{
-	XMP_OptionBits	options = 0;
-	
-	return options;
-	
-}	// GetGlobalOptions
-
-
-// -------------------------------------------------------------------------------------------------
-// SetGlobalOptions
-// ----------------
-
-/* class-static */ void
-XMPMeta::SetGlobalOptions ( XMP_OptionBits /*options*/ )
-{
-
-	XMP_Throw ( "Unimplemented method XMPMeta::SetGlobalOptions", kXMPErr_Unimplemented );
-
-}	// SetGlobalOptions
-
-
-// -------------------------------------------------------------------------------------------------
-// RegisterNamespace
-// -----------------
-
-/* class-static */ void
-XMPMeta::RegisterNamespace ( XMP_StringPtr	 namespaceURI,
-                             XMP_StringPtr	 prefix )
-{
-	if ( (*namespaceURI == 0) || (*prefix == 0) ) {
-		XMP_Throw ( "Empty namespace URI or prefix", kXMPErr_BadParam );
-	}
-	
-	XMP_VarString	nsURI ( namespaceURI );
-	XMP_VarString	prfix ( prefix );
-	if ( prfix[prfix.size()-1] != ':' ) prfix += ':';
-	VerifySimpleXMLName ( prefix, prefix+prfix.size()-1 );	// Exclude the colon.
-	
-        // Set the new namespace in both maps.
-        (*sNamespaceURIToPrefixMap)[nsURI] = prfix;
-        (*sNamespacePrefixToURIMap)[prfix] = nsURI;
-	
-}	// RegisterNamespace
-
-
-// -------------------------------------------------------------------------------------------------
-// GetNamespacePrefix
-// ------------------
-
-/* class-static */ bool
-XMPMeta::GetNamespacePrefix	( XMP_StringPtr   namespaceURI,
-							  XMP_StringPtr * namespacePrefix,
-							  XMP_StringLen * prefixSize )
-{
-	bool	found	= false;
-	
-	XMP_Assert ( *namespaceURI != 0 ); 	// ! Enforced by wrapper.
-	XMP_Assert ( (namespacePrefix != 0) && (prefixSize != 0) );	// ! Enforced by wrapper.
-
-	XMP_VarString    nsURI ( namespaceURI );
-	XMP_StringMapPos uriPos	= sNamespaceURIToPrefixMap->find ( nsURI );
-	
-	if ( uriPos != sNamespaceURIToPrefixMap->end() ) {
-		*namespacePrefix = uriPos->second.c_str();
-		*prefixSize = uriPos->second.size();
-		found = true;
-	}
-	
-	return found;
-	
-}	// GetNamespacePrefix
-
-
-// -------------------------------------------------------------------------------------------------
-// GetNamespaceURI
-// ---------------
-
-/* class-static */ bool
-XMPMeta::GetNamespaceURI ( XMP_StringPtr   namespacePrefix,
-						   XMP_StringPtr * namespaceURI,
-						   XMP_StringLen * uriSize )
-{
-	bool	found	= false;
-	
-	XMP_Assert ( *namespacePrefix != 0 ); 	// ! Enforced by wrapper.
-	XMP_Assert ( (namespacePrefix != 0) && (namespaceURI != 0) );	// ! Enforced by wrapper.
-
-	XMP_VarString nsPrefix ( namespacePrefix );
-	if ( nsPrefix[nsPrefix.size()-1] != ':' ) nsPrefix += ':';
-	
-	XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( nsPrefix );
-	
-	if ( prefixPos != sNamespacePrefixToURIMap->end() ) {
-		*namespaceURI = prefixPos->second.c_str();
-		*uriSize = prefixPos->second.size();
-		found = true;
-	}
-	
-	return found;
-	
-}	// GetNamespaceURI
-
-
-// -------------------------------------------------------------------------------------------------
-// DeleteNamespace
-// ---------------
-
-// *** Don't allow standard namespaces to be deleted.
-// *** We would be better off not having this. Instead, have local namespaces from parsing be
-// *** restricted to the object that introduced them.
-
-/* class-static */ void
-XMPMeta::DeleteNamespace ( XMP_StringPtr namespaceURI )
-{
-	XMP_StringMapPos uriPos = sNamespaceURIToPrefixMap->find ( namespaceURI );
-	if ( uriPos == sNamespaceURIToPrefixMap->end() ) return;
-
-	XMP_StringMapPos prefixPos = sNamespacePrefixToURIMap->find ( uriPos->second );
-	XMP_Assert ( prefixPos != sNamespacePrefixToURIMap->end() );
-	
-	sNamespaceURIToPrefixMap->erase ( uriPos );
-	sNamespacePrefixToURIMap->erase ( prefixPos );
-
-}	// DeleteNamespace
-
-
-// -------------------------------------------------------------------------------------------------
-// RegisterAlias
-// -------------
-//
-// Allow 3 kinds of alias: 
-//	TopProp => TopProp
-//	TopProp => TopArray[1]
-//	TopProp => TopArray[@xml:lang='x-default']
-//
-// A new alias can be made to something that is already aliased, as long as the net result is one of
-// the legitimate forms. The new alias can already have aliases to it, also as long as result of
-// adjusting all of the exiting aliases leaves them legal.
-//
-// ! The caller assumes all risk that new aliases do not invalidate existing XMPMeta objects. Any
-// ! conflicts will result in later references throwing bad XPath exceptions.
-
-/* class-static */ void
-XMPMeta::RegisterAlias ( XMP_StringPtr 	aliasNS,
-						 XMP_StringPtr	aliasProp,
-						 XMP_StringPtr	actualNS,
-						 XMP_StringPtr	actualProp,
-						 XMP_OptionBits arrayForm )
-{
-	XMP_ExpandedXPath	expAlias, expActual;
-	XMP_AliasMapPos		mapPos;
-	XMP_ExpandedXPath *	regActual = 0;
-
-	XMP_Assert ( (aliasNS != 0) && (aliasProp != 0) && (actualNS != 0) && (actualProp != 0) );	// Enforced by wrapper.
-		
-	// Expand the alias and actual names, make sure they are one of the basic 3 forms. When counting
-	// the expanded XPath size remember that the schema URI is the first component. We don't have to
-	// compare the schema URIs though, the (unique) prefix is part of the top property name.
-	
-	ExpandXPath ( aliasNS, aliasProp, &expAlias );
-	ExpandXPath ( actualNS, actualProp, &expActual );
-	if ( (expAlias.size() != 2) || (expActual.size() != 2) ) {
-		XMP_Throw ( "Alias and actual property names must be simple", kXMPErr_BadXPath );
-	}
-	
-	arrayForm = VerifySetOptions ( arrayForm, 0 );
-	if ( arrayForm != 0 ) {
-		if ( (arrayForm & ~kXMP_PropArrayFormMask) != 0 ) XMP_Throw ( "Only array form flags are allowed", kXMPErr_BadOptions );
-		expActual[1].options |= arrayForm;	// Set the array form for the top level step.
-		if ( ! (arrayForm & kXMP_PropArrayIsAltText) ) {
-			expActual.push_back ( XPathStepInfo ( "[1]", kXMP_ArrayIndexStep ) );
-		} else {
-			expActual.push_back ( XPathStepInfo ( "[?xml:lang=\"x-default\"]", kXMP_QualSelectorStep ) );
-		}
-	}
-
-	// See if there are any conflicts with existing aliases. A couple of the checks are easy. If the
-	// alias is already aliased it is only OK to reregister an identical alias. If the actual is
-	// already aliased to something else and the new chain is legal, just swap in the old base.
-
-	mapPos = sRegisteredAliasMap->find ( expAlias[kRootPropStep].step );
-	if ( mapPos != sRegisteredAliasMap->end() ) {
-
-		// This alias is already registered to something, make sure it is the same something.
-
-		regActual = &mapPos->second;
-		if ( arrayForm != (mapPos->second[1].options & kXMP_PropArrayFormMask) ) {
-			XMP_Throw ( "Mismatch with existing alias array form", kXMPErr_BadParam );
-		}
-		if ( expActual.size() != regActual->size() ) {
-			XMP_Throw ( "Mismatch with existing actual path", kXMPErr_BadParam );
-		}
-		if ( expActual[kRootPropStep].step != (*regActual)[kRootPropStep].step ) {
-			XMP_Throw ( "Mismatch with existing actual name", kXMPErr_BadParam );
-		}
-		if ( (expActual.size() == 3) && (expActual[kAliasIndexStep].step != (*regActual)[kAliasIndexStep].step) ) {
-			XMP_Throw ( "Mismatch with existing actual array item", kXMPErr_BadParam );
-		}
-		return;
-
-	}
-
-	mapPos = sRegisteredAliasMap->find ( expActual[kRootPropStep].step );
-	if ( mapPos != sRegisteredAliasMap->end() ) {
-	
-		// The actual is already aliased to something else.
-		
-		regActual = &mapPos->second;
-		if ( expActual.size() == 2 ) {
-			expActual = *regActual;	// TopProp => TopProp => anything : substitute the entire old base.
-		} else if ( regActual->size() != 2 ) {
-			XMP_Throw ( "Can't alias an array item to an array item", kXMPErr_BadParam );	// TopProp => TopArray[] => TopArray[] : nope.
-		} else {
-			expActual[kSchemaStep].step = (*regActual)[kSchemaStep].step;		// TopProp => TopArray[] => TopProp :
-			expActual[kRootPropStep].step   = (*regActual)[kRootPropStep].step;	//	substitute the old base name.
-		}
-	
-	}
-	
-	// Checking for existing aliases to this one is touchier. This involves updating the alias map,
-	// which must not be done unless all of the changes are legal. So we need 2 loops, one to verify
-	// that everything is OK, and one to make the changes. The bad case is:
-	//	TopProp => TopArray[] => TopArray[]
-	// In the valid cases we back substitute the new base.
-	
-	for ( mapPos = sRegisteredAliasMap->begin(); mapPos != sRegisteredAliasMap->end(); ++mapPos ) {
-		regActual = &mapPos->second;
-		if ( expAlias[kRootPropStep].step == (*regActual)[kRootPropStep].step ) {
-			if ( (regActual->size() == 2) && (expAlias.size() == 2) ) {
-				XMP_Throw ( "Can't alias an array item to an array item", kXMPErr_BadParam );
-			}
-		}
-	}
-	
-	for ( mapPos = sRegisteredAliasMap->begin(); mapPos != sRegisteredAliasMap->end(); ++mapPos ) {
-		regActual = &mapPos->second;
-		if ( expAlias[kRootPropStep].step == (*regActual)[kRootPropStep].step ) {
-
-			if ( regActual->size() == 1 ) {
-				*regActual = expActual;	// TopProp => TopProp => anything : substitute the entire new base.
-			} else {
-				(*regActual)[kSchemaStep].step = expActual[kSchemaStep].step;	// TopProp => TopArray[] => TopProp :
-				(*regActual)[kRootPropStep].step   = expActual[kRootPropStep].step;		//	substitute the new base name.
-			}
-
-		}
-	}
-	
-	// Finally, all is OK to register the new alias.
-	
-	(void) sRegisteredAliasMap->insert ( XMP_AliasMap::value_type ( expAlias[kRootPropStep].step, expActual ) );
-
-}	// RegisterAlias
-
-
-// -------------------------------------------------------------------------------------------------
-// ResolveAlias
-// ------------
-
-/* class-static */ bool
-XMPMeta::ResolveAlias ( XMP_StringPtr	 aliasNS,
-						XMP_StringPtr	 aliasProp,
-						XMP_StringPtr *	 actualNS,
-						XMP_StringLen *	 nsSize,
-						XMP_StringPtr *	 actualProp,
-						XMP_StringLen *	 propSize,
-						XMP_OptionBits * arrayForm )
-{
-	XMP_Assert ( (aliasNS != 0) && (aliasProp != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (actualNS != 0) && (nsSize != 0) && (actualProp != 0) && (propSize != 0) && (arrayForm != 0) );	// Enforced by wrapper.
-	
-	// Expand the input path and look up the first component in the alias table. Return if not an alias.
-	
-	XMP_ExpandedXPath fullPath, minPath;
-	ExpandXPath ( aliasNS, aliasProp, &fullPath );
-	XMP_Assert ( fullPath.size() >= 2 );
-
-	minPath.push_back ( fullPath[kSchemaStep] );
-	minPath.push_back ( fullPath[kRootPropStep] );
-	XMP_AliasMapPos mapPos = sRegisteredAliasMap->find ( minPath[kRootPropStep].step );
-	if ( mapPos == sRegisteredAliasMap->end() ) return false;
-	
-	// Replace the alias portion of the full expanded path. Compose the output path string.
-	
-	const XMP_ExpandedXPath & actualPath = mapPos->second;
-	
-	fullPath[kSchemaStep] = actualPath[kSchemaStep];
-	fullPath[kRootPropStep] = actualPath[kRootPropStep];
-	if ( actualPath.size() > 2 ) {	// This is an alias to an array item.
-		XMP_ExpandedXPathPos insertPos = fullPath.begin() + kAliasIndexStep;
-		fullPath.insert ( insertPos, actualPath[kAliasIndexStep] );
-	}	
-	
-	*sOutputNS = fullPath[kSchemaStep].step;
-	*actualNS  = sOutputNS->c_str();
-	*nsSize    = sOutputNS->size();
-	
-	ComposeXPath ( fullPath, sOutputStr );
-	*actualProp = sOutputStr->c_str();
-	*propSize   = sOutputStr->size();
-
-	*arrayForm  = actualPath[kRootPropStep].options & kXMP_PropArrayFormMask;
-	
-	#if XMP_DebugBuild	// Test that the output string is valid and unchanged by round trip expand/compose.
-		XMP_ExpandedXPath rtPath;
-		ExpandXPath ( *actualNS, *actualProp, &rtPath );
-		std::string rtString;
-		ComposeXPath ( rtPath, &rtString );
-		XMP_Assert ( rtString == *sOutputStr );
-	#endif
-	
-	return true;
-	
-}	// ResolveAlias
-
-
-// -------------------------------------------------------------------------------------------------
-// DeleteAlias
-// -----------
-
-/* class-static */ void
-XMPMeta::DeleteAlias ( XMP_StringPtr /*aliasNS*/,
-                       XMP_StringPtr /*aliasProp*/ )
-{
-
-//	Todo: XMP_Assert ( (aliasNS != 0) && (aliasProp != 0) );	/ / Enforced by wrapper.
-	XMP_Throw ( "Unimplemented method XMPMeta::DeleteAlias", kXMPErr_Unimplemented );   // *** #error "write me"
-
-}	// DeleteAlias
-
-
-// -------------------------------------------------------------------------------------------------
-// RegisterStandardAliases
-// -----------------------
-
-/* class-static */ void
-XMPMeta::RegisterStandardAliases ( XMP_StringPtr schemaNS )
-{
-	XMP_Assert ( schemaNS != 0 );	// Enforced by wrapper.
-
-	const bool doAll = (*schemaNS == 0);
-	
-	if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_XMP ) ) {
-		// Aliases from XMP to DC.
-	    XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Author",       kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered );
-	    XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Authors",      kXMP_NS_DC, "creator", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Description",  kXMP_NS_DC, "description", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Format",       kXMP_NS_DC, "format", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Keywords",     kXMP_NS_DC, "subject", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Locale",       kXMP_NS_DC, "language", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_XMP, "Title",        kXMP_NS_DC, "title", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_XMP_Rights, "Copyright", kXMP_NS_DC, "rights", 0 );
-	}
-
-	if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_PDF ) ) {
-		// Aliases from PDF to DC and XMP.
-	    XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Author",       kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered );
-	    XMPMeta::RegisterAlias ( kXMP_NS_PDF, "BaseURL",      kXMP_NS_XMP, "BaseURL", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_PDF, "CreationDate", kXMP_NS_XMP, "CreateDate", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Creator",      kXMP_NS_XMP, "CreatorTool", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_PDF, "ModDate",      kXMP_NS_XMP, "ModifyDate", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Subject",      kXMP_NS_DC,  "description", kXMP_PropArrayIsAltText );
-	    XMPMeta::RegisterAlias ( kXMP_NS_PDF, "Title",        kXMP_NS_DC,  "title", kXMP_PropArrayIsAltText );
-    }
-    
-	if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_Photoshop ) ) {
-	    // Aliases from PHOTOSHOP to DC and XMP.
-	    XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Author",       kXMP_NS_DC, "creator", kXMP_PropArrayIsOrdered );
-	    XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Caption",      kXMP_NS_DC, "description", kXMP_PropArrayIsAltText );
-	    XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Copyright",    kXMP_NS_DC, "rights", kXMP_PropArrayIsAltText );
-	    XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Keywords",     kXMP_NS_DC, "subject", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Marked",       kXMP_NS_XMP_Rights, "Marked", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "Title",        kXMP_NS_DC, "title", kXMP_PropArrayIsAltText );
-	    XMPMeta::RegisterAlias ( kXMP_NS_Photoshop, "WebStatement", kXMP_NS_XMP_Rights, "WebStatement", 0 );
-    }
-	    
-	if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_TIFF ) || XMP_LitMatch ( schemaNS, kXMP_NS_EXIF ) ) {
-	    // Aliases from TIFF and EXIF to DC and XMP.
-		XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "Artist",           kXMP_NS_DC,  "creator", kXMP_PropArrayIsOrdered);
-	    XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "Copyright",        kXMP_NS_DC,  "rights", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "DateTime",         kXMP_NS_XMP, "ModifyDate", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "ImageDescription", kXMP_NS_DC,  "description", 0 );
-	    XMPMeta::RegisterAlias ( kXMP_NS_TIFF, "Software",         kXMP_NS_XMP, "CreatorTool", 0 );
-    }
-    
-	if ( doAll || XMP_LitMatch ( schemaNS, kXMP_NS_PNG ) ) {	// ! From Acrobat ImageCapture:
-		XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Author",           kXMP_NS_DC,  "creator", kXMP_PropArrayIsOrdered);
-		XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Copyright",        kXMP_NS_DC,  "rights", kXMP_PropArrayIsAltText);
-		XMPMeta::RegisterAlias ( kXMP_NS_PNG, "CreationTime",     kXMP_NS_XMP, "CreateDate", 0 );
-		XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Description",      kXMP_NS_DC,  "description", kXMP_PropArrayIsAltText);
-		XMPMeta::RegisterAlias ( kXMP_NS_PNG, "ModificationTime", kXMP_NS_XMP, "ModifyDate", 0 );
-		XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Software",         kXMP_NS_XMP, "CreatorTool", 0 );
-		XMPMeta::RegisterAlias ( kXMP_NS_PNG, "Title",            kXMP_NS_DC,  "title", kXMP_PropArrayIsAltText);
-	}
-
-}	// RegisterStandardAliases
-
-
-// =================================================================================================
-// Class Methods
-// =============
-//
-//
-// =================================================================================================
-
-
-// -------------------------------------------------------------------------------------------------
-// DumpObject
-// ----------
-
-XMP_Status
-XMPMeta::DumpObject ( XMP_TextOutputProc outProc,
-                      void *             refCon ) const
-{
-	XMP_Assert ( outProc != 0 );	// ! Enforced by wrapper.
-	XMP_Status status = 0;
-	
-	OutProcLiteral ( "Dumping XMPMeta object \"" );
-	DumpClearString ( tree.name, outProc, refCon );
-	OutProcNChars ( "\"  ", 3 );
-	status = DumpNodeOptions ( tree.options, outProc, refCon );
-	if ( status != 0 ) goto EXIT;
-	#if 0	// *** XMP_DebugBuild
-		if ( (tree._namePtr != tree.name.c_str()) ||
-			 (tree._valuePtr != tree.value.c_str()) ) OutProcLiteral ( "  ** bad debug string **" );
-	#endif
-	OutProcNewline();
-	
-	if ( ! tree.value.empty() ) {
-		OutProcLiteral ( "** bad root value **  \"" );
-		DumpClearString ( tree.value, outProc, refCon );
-		OutProcNChars ( "\"", 1 );
-		OutProcNewline();
-	}
-
-	if ( ! tree.qualifiers.empty() ) {
-		OutProcLiteral ( "** bad root qualifiers **" );
-		OutProcNewline();
-		for ( size_t qualNum = 0, qualLim = tree.qualifiers.size(); qualNum < qualLim; ++qualNum ) {
-			status = DumpPropertyTree ( tree.qualifiers[qualNum], 3, 0, outProc, refCon );
-		}
-	}
-
-	if ( ! tree.children.empty() ) {
-
-		for ( size_t childNum = 0, childLim = tree.children.size(); childNum < childLim; ++childNum ) {
-
-			const XMP_Node * currSchema = tree.children[childNum];
-
-			OutProcNewline();
-			OutProcIndent ( 1 );
-			DumpClearString ( currSchema->value, outProc, refCon );
-			OutProcNChars ( "  ", 2 );
-			DumpClearString ( currSchema->name, outProc, refCon );
-			OutProcNChars ( "  ", 2 );
-			status = DumpNodeOptions ( currSchema->options, outProc, refCon );
-			if ( status != 0 ) goto EXIT;
-			#if 0	// *** XMP_DebugBuild
-				if ( (currSchema->_namePtr != currSchema->name.c_str()) ||
-					 (currSchema->_valuePtr != currSchema->value.c_str()) ) OutProcLiteral ( "  ** bad debug string **" );
-			#endif
-			OutProcNewline();
-
-			if ( ! (currSchema->options & kXMP_SchemaNode) ) {
-				OutProcLiteral ( "** bad schema options **" );
-				OutProcNewline();
-			}
-
-			if ( ! currSchema->qualifiers.empty() ) {
-				OutProcLiteral ( "** bad schema qualifiers **" );
-				OutProcNewline();
-				for ( size_t qualNum = 0, qualLim = currSchema->qualifiers.size(); qualNum < qualLim; ++qualNum ) {
-					DumpPropertyTree ( currSchema->qualifiers[qualNum], 3, 0, outProc, refCon );
-				}
-			}
-
-			for ( size_t childNum = 0, childLim = currSchema->children.size(); childNum < childLim; ++childNum ) {
-				DumpPropertyTree ( currSchema->children[childNum], 2, 0, outProc, refCon );
-			}
-
-		}
-
-	}
-	
-EXIT:
-	return status;
-
-}	// DumpObject
-
-
-// -------------------------------------------------------------------------------------------------
-// CountArrayItems
-// ---------------
-
-XMP_Index
-XMPMeta::CountArrayItems ( XMP_StringPtr schemaNS,
-						   XMP_StringPtr arrayName ) const
-{
-	XMP_Assert ( (schemaNS != 0) && (arrayName != 0) );	// Enforced by wrapper.
-
-	XMP_ExpandedXPath	expPath;
-	ExpandXPath ( schemaNS, arrayName, &expPath );
-	
-	const XMP_Node * arrayNode = FindConstNode ( &tree, expPath );
-
-	if ( arrayNode == 0 ) return 0;
-	if ( ! (arrayNode->options & kXMP_PropValueIsArray) ) XMP_Throw ( "The named property is not an array", kXMPErr_BadXPath );
-	return arrayNode->children.size();
-	
-}	// CountArrayItems
-
-
-// -------------------------------------------------------------------------------------------------
-// GetObjectName
-// -------------
-
-void
-XMPMeta::GetObjectName ( XMP_StringPtr * namePtr,
-						 XMP_StringLen * nameLen ) const
-{
-	
-	*namePtr = tree.name.c_str();
-	*nameLen = tree.name.size();
-	
-}	// GetObjectName
-
-
-// -------------------------------------------------------------------------------------------------
-// SetObjectName
-// -------------
-
-void
-XMPMeta::SetObjectName ( XMP_StringPtr name )
-{
-	VerifyUTF8 ( name );	// Throws if the string is not legit UTF-8.
-	tree.name = name;
-
-}	// SetObjectName
-
-
-// -------------------------------------------------------------------------------------------------
-// GetObjectOptions
-// ----------------
-
-XMP_OptionBits
-XMPMeta::GetObjectOptions() const
-{
-	XMP_OptionBits	options	= 0;
-	
-	return options;
-	
-}	// GetObjectOptions
-
-
-// -------------------------------------------------------------------------------------------------
-// SetObjectOptions
-// ----------------
-
-void
-XMPMeta::SetObjectOptions ( XMP_OptionBits /*options*/ )
-{
-
-	XMP_Throw ( "Unimplemented method XMPMeta::SetObjectOptions", kXMPErr_Unimplemented );
-
-}	// SetObjectOptions
-
-
-// -------------------------------------------------------------------------------------------------
-// Sort
-// ----
-//
-// At the top level the namespaces are sorted by their prefixes. Within a namespace, the top level
-// properties are sorted by name. Within a struct, the fields are sorted by their qualified name,
-// i.e. their XML prefix:local form. Unordered arrays of simple items are sorted by value. Language
-// Alternative arrays are sorted by the xml:lang qualifiers, with the "x-default" item placed first.
-
-void
-XMPMeta::Sort()
-{
-
-	if ( ! this->tree.qualifiers.empty() ) {
-		sort ( this->tree.qualifiers.begin(), this->tree.qualifiers.end(), CompareNodeNames );
-		SortWithinOffspring ( this->tree.qualifiers );
-	}
-
-	if ( ! this->tree.children.empty() ) {
-		// The schema prefixes are the node's value, the name is the URI, so we sort schemas by value.
-		sort ( this->tree.children.begin(), this->tree.children.end(), CompareNodeValues );
-		SortWithinOffspring ( this->tree.children );
-	}
-
-}	// Sort
-
-
-// -------------------------------------------------------------------------------------------------
-// Erase
-// -----
-//
-// Clear everything except for clientRefs.
-
-void
-XMPMeta::Erase()
-{
-
-	this->prevTkVer = 0;
-	if ( this->xmlParser != 0 ) {
-		delete ( this->xmlParser );
-		this->xmlParser = 0;
-	}
-	this->tree.ClearNode();
-
-}	// Erase
-
-
-// -------------------------------------------------------------------------------------------------
-// Clone
-// -----
-
-void
-XMPMeta::Clone ( XMPMeta * clone, XMP_OptionBits options ) const
-{
-	if ( clone == 0 ) XMP_Throw ( "Null clone pointer", kXMPErr_BadParam );
-	if ( options != 0 ) XMP_Throw ( "No options are defined yet", kXMPErr_BadOptions );
-	XMP_Assert ( this->tree.parent == 0 );
-
-	clone->tree.ClearNode();
-	
-	clone->tree.options = this->tree.options;
-	clone->tree.name    = this->tree.name;
-	clone->tree.value   = this->tree.value;
-
-	#if 0	// *** XMP_DebugBuild
-		clone->tree._namePtr = clone->tree.name.c_str();
-		clone->tree._valuePtr = clone->tree.value.c_str();
-	#endif
-	
-	CloneOffspring ( &this->tree, &clone->tree );
-	
-}	// Clone
-
-// =================================================================================================
diff --git a/xmpsdk/src/XMPMeta.hpp b/xmpsdk/src/XMPMeta.hpp
deleted file mode 100644
index 68462dce..00000000
--- a/xmpsdk/src/XMPMeta.hpp
+++ /dev/null
@@ -1,418 +0,0 @@
-#ifndef __XMPMeta_hpp__
-#define __XMPMeta_hpp__
-
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:	Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"
-#include "XMP_Const.h"
-#include "XMPCore_Impl.hpp"
-#include "XMLParserAdapter.hpp"
-
-// -------------------------------------------------------------------------------------------------
-
-#ifndef DumpXMLParseTree
-	#define DumpXMLParseTree 0
-#endif
-
-extern XMP_VarString * xdefaultName;
-
-class XMPIterator;
-class XMPUtils;
-
-// -------------------------------------------------------------------------------------------------
-
-class XMPMeta {
-public:
-
-	static void
-	GetVersionInfo ( XMP_VersionInfo * info );
-	
-	static bool
-	Initialize();
-	static void
-	Terminate() RELEASE_NO_THROW;
-	
-	static void
-	Unlock ( XMP_OptionBits options );
-
-	// ---------------------------------------------------------------------------------------------
-
-	XMPMeta();
-	
-	virtual ~XMPMeta() RELEASE_NO_THROW;
-
-	// ---------------------------------------------------------------------------------------------
-	
-	static XMP_OptionBits
-	GetGlobalOptions();
-	
-	static void
-	SetGlobalOptions ( XMP_OptionBits options );
-
-	// ---------------------------------------------------------------------------------------------
-
-	static XMP_Status
-	DumpNamespaces ( XMP_TextOutputProc outProc,
-					 void *				refCon );
-	
-	static XMP_Status
-	DumpAliases ( XMP_TextOutputProc outProc,
-				  void *			 refCon );
-	
-	// ---------------------------------------------------------------------------------------------
-	
-	static void
-	RegisterNamespace ( XMP_StringPtr	namespaceURI,
-                            XMP_StringPtr	prefix );
-	
-	static bool
-	GetNamespacePrefix ( XMP_StringPtr	 namespaceURI,
-						 XMP_StringPtr * namespacePrefix,
-						 XMP_StringLen * prefixSize );
-	
-	static bool
-	GetNamespaceURI ( XMP_StringPtr	  namespacePrefix,
-					  XMP_StringPtr * namespaceURI,
-					  XMP_StringLen * uriSize );
-	
-	static void
-	DeleteNamespace ( XMP_StringPtr namespaceURI );
-
-	// ---------------------------------------------------------------------------------------------
-	
-	static void
-	RegisterAlias ( XMP_StringPtr  aliasNS,
-					XMP_StringPtr  aliasProp,
-					XMP_StringPtr  actualNS,
-					XMP_StringPtr  actualProp,
-					XMP_OptionBits arrayForm );
-	
-	static bool
-	ResolveAlias ( XMP_StringPtr	aliasNS,
-				   XMP_StringPtr	aliasProp,
-				   XMP_StringPtr *	actualNS,
-				   XMP_StringLen *	nsSize,
-				   XMP_StringPtr *	actualProp,
-				   XMP_StringLen *	propSize,
-				   XMP_OptionBits * arrayForm );
-	
-	static void
-	DeleteAlias ( XMP_StringPtr aliasNS,
-				  XMP_StringPtr aliasProp );
-	
-	static void
-	RegisterStandardAliases ( XMP_StringPtr schemaNS );
-
-	// ---------------------------------------------------------------------------------------------
-	
-	void
-	UnlockObject ( XMP_OptionBits options ) const;
-	
-	// ---------------------------------------------------------------------------------------------
-	
-	bool
-	GetProperty ( XMP_StringPtr	   schemaNS,
-				  XMP_StringPtr	   propName,
-				  XMP_StringPtr *  propValue,
-				  XMP_StringLen *  valueSize,
-				  XMP_OptionBits * options ) const;
-	
-	bool
-	GetArrayItem ( XMP_StringPtr	schemaNS,
-				   XMP_StringPtr	arrayName,
-				   XMP_Index		itemIndex,
-				   XMP_StringPtr *	itemValue,
-				   XMP_StringLen *	valueSize,
-				   XMP_OptionBits * options ) const;
-	
-	bool
-	GetStructField ( XMP_StringPtr	  schemaNS,
-					 XMP_StringPtr	  structName,
-					 XMP_StringPtr	  fieldNS,
-					 XMP_StringPtr	  fieldName,
-					 XMP_StringPtr *  fieldValue,
-					 XMP_StringLen *  valueSize,
-					 XMP_OptionBits * options ) const;
-	
-	bool
-	GetQualifier ( XMP_StringPtr	schemaNS,
-				   XMP_StringPtr	propName,
-				   XMP_StringPtr	qualNS,
-				   XMP_StringPtr	qualName,
-				   XMP_StringPtr *	qualValue,
-				   XMP_StringLen *	valueSize,
-				   XMP_OptionBits * options ) const;
-	
-	// ---------------------------------------------------------------------------------------------
-	
-	void
-	SetProperty ( XMP_StringPtr	 schemaNS,
-				  XMP_StringPtr	 propName,
-				  XMP_StringPtr	 propValue,
-				  XMP_OptionBits options );
-	
-	void
-	SetArrayItem ( XMP_StringPtr  schemaNS,
-				   XMP_StringPtr  arrayName,
-				   XMP_Index	  itemIndex,
-				   XMP_StringPtr  itemValue,
-				   XMP_OptionBits options );
-	
-	void
-	AppendArrayItem ( XMP_StringPtr	 schemaNS,
-					  XMP_StringPtr	 arrayName,
-					  XMP_OptionBits arrayOptions,
-					  XMP_StringPtr	 itemValue,
-					  XMP_OptionBits options );
-	
-	void
-	SetStructField ( XMP_StringPtr	schemaNS,
-					 XMP_StringPtr	structName,
-					 XMP_StringPtr	fieldNS,
-					 XMP_StringPtr	fieldName,
-					 XMP_StringPtr	fieldValue,
-					 XMP_OptionBits options );
-	
-	void
-	SetQualifier ( XMP_StringPtr  schemaNS,
-				   XMP_StringPtr  propName,
-				   XMP_StringPtr  qualNS,
-				   XMP_StringPtr  qualName,
-				   XMP_StringPtr  qualValue,
-				   XMP_OptionBits options );
-	
-	// ---------------------------------------------------------------------------------------------
-	
-	void
-	DeleteProperty ( XMP_StringPtr schemaNS,
-					 XMP_StringPtr propName );
-	
-	void
-	DeleteArrayItem ( XMP_StringPtr schemaNS,
-					  XMP_StringPtr arrayName,
-					  XMP_Index		itemIndex );
-	
-	void
-	DeleteStructField ( XMP_StringPtr schemaNS,
-						XMP_StringPtr structName,
-						XMP_StringPtr fieldNS,
-						XMP_StringPtr fieldName );
-	
-	void
-	DeleteQualifier ( XMP_StringPtr schemaNS,
-					  XMP_StringPtr propName,
-					  XMP_StringPtr qualNS,
-					  XMP_StringPtr qualName );
-	
-	// ---------------------------------------------------------------------------------------------
-	
-	bool
-	DoesPropertyExist ( XMP_StringPtr schemaNS,
-						XMP_StringPtr propName ) const;
-	
-	bool
-	DoesArrayItemExist ( XMP_StringPtr schemaNS,
-						 XMP_StringPtr arrayName,
-						 XMP_Index	   itemIndex ) const;
-	
-	bool
-	DoesStructFieldExist ( XMP_StringPtr schemaNS,
-						   XMP_StringPtr structName,
-						   XMP_StringPtr fieldNS,
-						   XMP_StringPtr fieldName ) const;
-	
-	bool
-	DoesQualifierExist ( XMP_StringPtr schemaNS,
-						 XMP_StringPtr propName,
-						 XMP_StringPtr qualNS,
-						 XMP_StringPtr qualName ) const;
-	
-	// ---------------------------------------------------------------------------------------------
-	
-	bool
-	GetLocalizedText ( XMP_StringPtr	schemaNS,
-					   XMP_StringPtr	altTextName,
-					   XMP_StringPtr	genericLang,
-					   XMP_StringPtr	specificLang,
-					   XMP_StringPtr *	actualLang,
-					   XMP_StringLen *	langSize,
-					   XMP_StringPtr *	itemValue,
-					   XMP_StringLen *	valueSize,
-					   XMP_OptionBits * options ) const;
-	
-	void
-	SetLocalizedText ( XMP_StringPtr  schemaNS,
-					   XMP_StringPtr  altTextName,
-					   XMP_StringPtr  genericLang,
-					   XMP_StringPtr  specificLang,
-					   XMP_StringPtr  itemValue,
-					   XMP_OptionBits options );
-	
-	// ---------------------------------------------------------------------------------------------
-	
-	bool
-	GetProperty_Bool ( XMP_StringPtr	schemaNS,
-					   XMP_StringPtr	propName,
-					   bool *			propValue,
-					   XMP_OptionBits * options ) const;
-	
-	bool
-	GetProperty_Int ( XMP_StringPtr	   schemaNS,
-					  XMP_StringPtr	   propName,
-					  XMP_Int32 *	   propValue,
-					  XMP_OptionBits * options ) const;
-	
-	bool
-	GetProperty_Int64 ( XMP_StringPtr	 schemaNS,
-					    XMP_StringPtr	 propName,
-					    XMP_Int64 *	     propValue,
-					    XMP_OptionBits * options ) const;
-	
-	bool
-	GetProperty_Float ( XMP_StringPtr	 schemaNS,
-						XMP_StringPtr	 propName,
-						double *		 propValue,
-						XMP_OptionBits * options ) const;
-	
-	bool
-	GetProperty_Date ( XMP_StringPtr	schemaNS,
-					   XMP_StringPtr	propName,
-					   XMP_DateTime *	propValue,
-					   XMP_OptionBits * options ) const;
-	
-	// ---------------------------------------------------------------------------------------------
-	
-	void
-	SetProperty_Bool ( XMP_StringPtr  schemaNS,
-					   XMP_StringPtr  propName,
-					   bool			  propValue,
-					   XMP_OptionBits options );
-	
-	void
-	SetProperty_Int ( XMP_StringPtr	 schemaNS,
-					  XMP_StringPtr	 propName,
-					  XMP_Int32		 propValue,
-					  XMP_OptionBits options );
-	
-	void
-	SetProperty_Int64 ( XMP_StringPtr  schemaNS,
-					    XMP_StringPtr  propName,
-					    XMP_Int64	   propValue,
-					    XMP_OptionBits options );
-	
-	void
-	SetProperty_Float ( XMP_StringPtr  schemaNS,
-						XMP_StringPtr  propName,
-						double		   propValue,
-						XMP_OptionBits options );
-	
-	void
-	SetProperty_Date ( XMP_StringPtr		schemaNS,
-					   XMP_StringPtr		propName,
-					   const XMP_DateTime & propValue,
-					   XMP_OptionBits		options );
-	
-	// ---------------------------------------------------------------------------------------------
-	
-	void
-	GetObjectName ( XMP_StringPtr * namePtr,
-					XMP_StringLen * nameLen ) const;
-
-	void
-	SetObjectName ( XMP_StringPtr name );
-
-	XMP_OptionBits
-	GetObjectOptions() const;
-	
-	void
-	SetObjectOptions ( XMP_OptionBits options );
-
-	void
-	Sort();
-
-	void
-	Erase();
-
-	void
-	Clone ( XMPMeta * clone, XMP_OptionBits options ) const;
-	
-	XMP_Index
-	CountArrayItems ( XMP_StringPtr schemaNS,
-					  XMP_StringPtr arrayName ) const;
-	
-	XMP_Status
-	DumpObject ( XMP_TextOutputProc outProc,
-				 void *				refCon ) const;
-	
-	// ---------------------------------------------------------------------------------------------
-	
-	void
-	ParseFromBuffer ( XMP_StringPtr	 buffer,
-					  XMP_StringLen	 bufferSize,
-					  XMP_OptionBits options );
-	
-	void
-	SerializeToBuffer ( XMP_StringPtr * rdfString,
-						XMP_StringLen * rdfSize,
-						XMP_OptionBits	options,
-						XMP_StringLen	padding,
-						XMP_StringPtr	newline,
-						XMP_StringPtr	indent,
-						XMP_Index		baseIndent ) const;
-	
-	// =============================================================================================
-
-	// ---------------------------------------------------------------------------------------------
-	// - Everything is built out of standard nodes. Each node has a name, value, option flags, a
-	// vector of child nodes, and a vector of qualifier nodes.
-	//
-	// - The option flags are those passed to SetProperty and returned from GetProperty. They tell
-	// if the node is simple, a struct or an array; whether it has qualifiers, etc.
-	//
-	// - The name of the node is an XML qualified name, of the form "prefix:simple-name". Since we
-	// force all namespaces to be known and to have unique prefixes, this is semantically equivalent
-	// to using a URI and simple name pair.
-	//
-	// - Although the value part is only for leaf properties and the children part is only for
-	// structs and arrays, it is easier to simply have them in every node. This keeps things visible
-	// so that debugging is easier
-	//
-	// - The top level node children are the namespaces that contain properties, the next level are
-	// the top level properties, lower levels are the fields of structs or items of arrays. The name
-	// of the top level nodes is just the namespace prefix, with the colon terminator. The name of
-	// top level properties includes the namespace prefix.
-	//
-	// - Any property node, at any level, can have qualifiers. These are themselves general property
-	// nodes. And could in fact themselves have qualifiers!
-
-	// ! Expose the implementation so that file static functions can see the data.
-
-	XMP_Int32 clientRefs;	// ! Must be signed to allow decrement from 0.
-	XMP_Int32 prevTkVer;	// Previous toolkit version as MMmmuubbb (major, minor, micro, build).
-	XMP_Node  tree;
-
-	XMLParserAdapter * xmlParser;
-	
-	friend class XMPIterator;
-	friend class XMPUtils;
-
-private:
-  
-	// ! These are hidden on purpose:
-	XMPMeta ( const XMPMeta & /* original */ ) : clientRefs(0), prevTkVer(0), tree(XMP_Node(0,"",0)), xmlParser(0)
-		{ XMP_Throw ( "Call to hidden constructor", kXMPErr_InternalFailure ); };
-	void operator= ( const XMPMeta & /* rhs */ )  
-		{ XMP_Throw ( "Call to hidden operator=", kXMPErr_InternalFailure ); };
-
-};	// class XMPMeta
-
-
-// =================================================================================================
-
-#endif	// __XMPMeta_hpp__
diff --git a/xmpsdk/src/XMPUtils-FileInfo.cpp b/xmpsdk/src/XMPUtils-FileInfo.cpp
deleted file mode 100644
index 6a79a2bf..00000000
--- a/xmpsdk/src/XMPUtils-FileInfo.cpp
+++ /dev/null
@@ -1,1346 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:	Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-
-#include "XMPUtils.hpp"
-
-#include <time.h>
-#include <string.h>
-#include <stdlib.h>
-#include <locale.h>
-#include <errno.h>
-
-#include <stdio.h>	// For snprintf.
-
-#if XMP_WinBuild
-#ifdef _MSC_VER
-	#pragma warning ( disable : 4800 )	// forcing value to bool 'true' or 'false' (performance warning)
-#endif
-#endif
-
-// =================================================================================================
-// Local Types and Constants
-// ========================= 
-
-typedef unsigned long	UniCodePoint;
-
-enum UniCharKind {
-	UCK_normal,
-	UCK_space,
-	UCK_comma,
-	UCK_semicolon,
-	UCK_quote,
-	UCK_control
-};
-typedef enum UniCharKind	UniCharKind;
-
-#define UnsByte(c)	((unsigned char)(c))
-#define UCP(u)		((UniCodePoint)(u))
-	// ! Needed on Windows (& PC Linux?) for inequalities with literals ito avoid sign extension.
-
-#ifndef TraceMultiFile
-	#define TraceMultiFile	0
-#endif
-
-// =================================================================================================
-// Static Variables
-// ================
-
-// =================================================================================================
-// Local Utilities
-// ===============
-
-// -------------------------------------------------------------------------------------------------
-// ClassifyCharacter
-// -----------------
-
-static void
-ClassifyCharacter ( XMP_StringPtr fullString, size_t offset,
-					UniCharKind * charKind, size_t * charSize, UniCodePoint * uniChar )
-{
-	*charKind = UCK_normal; // Assume typical case.
-	
-	unsigned char	currByte = UnsByte ( fullString[offset] );
-	
-	if ( currByte < UnsByte(0x80) ) {
-	
-		// ----------------------------------------
-		// We've got a single byte ASCII character.
-
-		*charSize = 1;
-		*uniChar = currByte;
-
-		if ( currByte > UnsByte(0x22) ) {
-
-			if ( currByte == UnsByte(0x2C) ) {
-				*charKind = UCK_comma;
-			} else if ( currByte == UnsByte(0x3B) ) {
-				*charKind = UCK_semicolon;
-			} else if ( (currByte == UnsByte(0x5B)) || (currByte == UnsByte(0x5D)) ) {
-				*charKind = UCK_quote;	// ! ASCII '[' and ']' are used as quotes in Chinese and Korean.
-			}
-
-		} else {	// currByte <= 0x22
-
-			if ( currByte == UnsByte(0x22) ) {
-				*charKind = UCK_quote;
-			} else if ( currByte == UnsByte(0x21) ) {
-				*charKind = UCK_normal;
-			} else if ( currByte == UnsByte(0x20) ) {
-				*charKind = UCK_space;
-			} else {
-				*charKind = UCK_control;
-			}
-
-		}
-
-	} else {	// currByte >= 0x80
-	
-		// ---------------------------------------------------------------------------------------
-		// We've got a multibyte Unicode character. The first byte has the number of bytes and the
-		// highest order bits. The other bytes each add 6 more bits. Compose the UTF-32 form so we
-		// can classify directly with the Unicode code points. Order the upperBits tests to be
-		// fastest for Japan, probably the most common non-ASCII usage.
-		
-		*charSize = 0;
-		*uniChar = currByte;
-		while ( (*uniChar & 0x80) != 0 ) {	// Count the leading 1 bits in the byte.
-			++(*charSize);
-			*uniChar = *uniChar << 1;
-		}
-		XMP_Assert ( (offset + *charSize) <= strlen(fullString) );
-		
-		*uniChar = *uniChar & 0x7F;			// Put the character bits in the bottom of uniChar.
-		*uniChar = *uniChar >> *charSize;
-		
-		for ( size_t i = (offset + 1); i < (offset + *charSize); ++i ) {
-			*uniChar = (*uniChar << 6) | (UnsByte(fullString[i]) & 0x3F);
-		}
-		
-		XMP_Uns32 upperBits = *uniChar >> 8;	// First filter on just the high order 24 bits.
-
-		if ( upperBits == 0xFF ) {			// U+FFxx
-
-			if ( *uniChar == UCP(0xFF0C) ) {
-				*charKind = UCK_comma;			// U+FF0C, full width comma.
-			} else if ( *uniChar == UCP(0xFF1B) ) {
-				*charKind = UCK_semicolon;		// U+FF1B, full width semicolon.
-			} else if ( *uniChar == UCP(0xFF64) ) {
-				*charKind = UCK_comma;			// U+FF64, half width ideographic comma.
-			}
-
-		} else if ( upperBits == 0xFE ) {	// U+FE--
-
-			if ( *uniChar == UCP(0xFE50) ) {
-				*charKind = UCK_comma;			// U+FE50, small comma.
-			} else if ( *uniChar == UCP(0xFE51) ) {
-				*charKind = UCK_comma;			// U+FE51, small ideographic comma.
-			} else if ( *uniChar == UCP(0xFE54) ) {
-				*charKind = UCK_semicolon;		// U+FE54, small semicolon.
-			}
-
-		} else if ( upperBits == 0x30 ) {	// U+30--
-
-			if ( *uniChar == UCP(0x3000) ) {
-				*charKind = UCK_space;			// U+3000, ideographic space.
-			} else if ( *uniChar == UCP(0x3001) ) {
-				*charKind = UCK_comma;			// U+3001, ideographic comma.
-			} else if ( (UCP(0x3008) <= *uniChar) && (*uniChar <= UCP(0x300F)) ) {
-				*charKind = UCK_quote;			// U+3008..U+300F, various quotes.
-			} else if ( *uniChar == UCP(0x303F) ) {
-				*charKind = UCK_space;			// U+303F, ideographic half fill space.
-			} else if ( (UCP(0x301D) <= *uniChar) && (*uniChar <= UCP(0x301F)) ) {
-				*charKind = UCK_quote;			// U+301D..U+301F, double prime quotes.
-			}
-
-		} else if ( upperBits == 0x20 ) {	// U+20--
-
-			if ( (UCP(0x2000) <= *uniChar) && (*uniChar <= UCP(0x200B)) ) {
-				*charKind = UCK_space;			// U+2000..U+200B, en quad through zero width space.
-			} else if ( *uniChar == UCP(0x2015) ) {
-				*charKind = UCK_quote;			// U+2015, dash quote.
-			} else if ( (UCP(0x2018) <= *uniChar) && (*uniChar <= UCP(0x201F)) ) {
-				*charKind = UCK_quote;			// U+2018..U+201F, various quotes.
-			} else if ( *uniChar == UCP(0x2028) ) {
-				*charKind = UCK_control;			// U+2028, line separator.
-			} else if ( *uniChar == UCP(0x2029) ) {
-				*charKind = UCK_control;			// U+2029, paragraph separator.
-			} else if ( (*uniChar == UCP(0x2039)) || (*uniChar == UCP(0x203A)) ) {
-				*charKind = UCK_quote;			// U+2039 and U+203A, guillemet quotes.
-			}
-
-		} else if ( upperBits == 0x06 ) {	// U+06--
-
-			if ( *uniChar == UCP(0x060C) ) {
-				*charKind = UCK_comma;			// U+060C, Arabic comma.
-			} else if ( *uniChar == UCP(0x061B) ) {
-				*charKind = UCK_semicolon;		// U+061B, Arabic semicolon.
-			}
-
-		} else if ( upperBits == 0x05 ) {	// U+05--
-
-			if ( *uniChar == UCP(0x055D) ) {
-				*charKind = UCK_comma;			// U+055D, Armenian comma.
-			}
-
-		} else if ( upperBits == 0x03 ) {	// U+03--
-
-			if ( *uniChar == UCP(0x037E) ) {
-				*charKind = UCK_semicolon;		// U+037E, Greek "semicolon" (really a question mark).
-			}
-
-		} else if ( upperBits == 0x00 ) {	// U+00--
-
-			if ( (*uniChar == UCP(0x00AB)) || (*uniChar == UCP(0x00BB)) ) {
-				*charKind = UCK_quote;			// U+00AB and U+00BB, guillemet quotes.
-			}
-
-		}
-				
-	}
-
-}	// ClassifyCharacter
-
-
-// -------------------------------------------------------------------------------------------------
-// IsClosingingQuote
-// -----------------
-
-static inline bool
-IsClosingingQuote ( UniCodePoint uniChar, UniCodePoint openQuote, UniCodePoint closeQuote )
-{
-
-	if ( (uniChar == closeQuote) ||
-		 ( (openQuote == UCP(0x301D)) && ((uniChar == UCP(0x301E)) || (uniChar == UCP(0x301F))) ) ) {
-		return true;
-	} else {
-		return false;
-	}
-
-}	// IsClosingingQuote
-
-
-// -------------------------------------------------------------------------------------------------
-// IsSurroundingQuote
-// ------------------
-
-static inline bool
-IsSurroundingQuote ( UniCodePoint uniChar, UniCodePoint openQuote, UniCodePoint closeQuote )
-{
-
-	if ( (uniChar == openQuote) || IsClosingingQuote ( uniChar, openQuote, closeQuote ) ) {
-		return true;
-	} else {
-		return false;
-	}
-
-}	// IsSurroundingQuote
-
-
-// -------------------------------------------------------------------------------------------------
-// GetClosingQuote
-// ---------------
-
-static UniCodePoint
-GetClosingQuote ( UniCodePoint openQuote )
-{
-	UniCodePoint	closeQuote;
-	
-	switch ( openQuote ) {
-
-		case UCP(0x0022) : closeQuote = UCP(0x0022);	// ! U+0022 is both opening and closing.
-						   break;
-		case UCP(0x005B) : closeQuote = UCP(0x005D);
-						   break;
-		case UCP(0x00AB) : closeQuote = UCP(0x00BB);	// ! U+00AB and U+00BB are reversible.
-						   break;
-		case UCP(0x00BB) : closeQuote = UCP(0x00AB);
-						   break;
-		case UCP(0x2015) : closeQuote = UCP(0x2015);	// ! U+2015 is both opening and closing.
-						   break;
-		case UCP(0x2018) : closeQuote = UCP(0x2019);
-						   break;
-		case UCP(0x201A) : closeQuote = UCP(0x201B);
-						   break;
-		case UCP(0x201C) : closeQuote = UCP(0x201D);
-						   break;
-		case UCP(0x201E) : closeQuote = UCP(0x201F);
-						   break;
-		case UCP(0x2039) : closeQuote = UCP(0x203A);	// ! U+2039 and U+203A are reversible.
-						   break;
-		case UCP(0x203A) : closeQuote = UCP(0x2039);
-						   break;
-		case UCP(0x3008) : closeQuote = UCP(0x3009);
-						   break;
-		case UCP(0x300A) : closeQuote = UCP(0x300B);
-						   break;
-		case UCP(0x300C) : closeQuote = UCP(0x300D);
-						   break;
-		case UCP(0x300E) : closeQuote = UCP(0x300F);
-						   break;
-		case UCP(0x301D) : closeQuote = UCP(0x301F);	// ! U+301E also closes U+301D.
-						   break;
-		default			 : closeQuote = 0;
-						   break;
-
-	}
-	
-	return closeQuote;
-	
-}	// GetClosingQuote
-
-
-// -------------------------------------------------------------------------------------------------
-// CodePointToUTF8
-// ---------------
-
-static void
-CodePointToUTF8 ( UniCodePoint uniChar, XMP_VarString & utf8Str )
-{
-	size_t i, byteCount;
-	XMP_Uns8 buffer [8];
-	UniCodePoint cpTemp;
-	
-	if ( uniChar <= 0x7F ) {
-
-		i = 7;
-		byteCount = 1;
-		buffer[7] = char(uniChar);
-	
-	} else {
-
-		// ---------------------------------------------------------------------------------------
-		// Copy the data bits from the low order end to the high order end, include the 0x80 mask.
-		
-		i = 8;
-		cpTemp = uniChar;
-		while ( cpTemp != 0 ) {
-			-- i;	// Exit with i pointing to the last byte stored.
-			buffer[i] = UnsByte(0x80) | (UnsByte(cpTemp) & 0x3F);
-			cpTemp = cpTemp >> 6;
-		}
-		byteCount = 8 - i;	// The total number of bytes needed.
-		XMP_Assert ( (2 <= byteCount) && (byteCount <= 6) );
-
-		// -------------------------------------------------------------------------------------
-		// Make sure the high order byte can hold the byte count mask, compute and set the mask.
-		
-		size_t bitCount = 0;	// The number of data bits in the first byte.
-		for ( cpTemp = (buffer[i] & UnsByte(0x3F)); cpTemp != 0; cpTemp = cpTemp >> 1 ) bitCount += 1;
-		if ( bitCount > (8 - (byteCount + 1)) ) byteCount += 1;
-		
-		i = 8 - byteCount;	// First byte index and mask shift count.
-		XMP_Assert ( (0 <= i) && (i <= 6) );
-		buffer[i] |= (UnsByte(0xFF) << i) & UnsByte(0xFF);	// AUDIT: Safe, i is between 0 and 6.
-	
-	}
-	
-	utf8Str.assign ( (char*)(&buffer[i]), byteCount );
-	
-}	// CodePointToUTF8
-
-
-// -------------------------------------------------------------------------------------------------
-// ApplyQuotes
-// -----------
-
-static void
-ApplyQuotes ( XMP_VarString * item, UniCodePoint openQuote, UniCodePoint closeQuote, bool allowCommas )
-{
-	bool	prevSpace	= false;
-	size_t	charOffset, charLen;
-	UniCharKind		charKind;
-	UniCodePoint	uniChar;
-	
-	// -----------------------------------------------------------------------------------------
-	// See if there are any separators in the value. Stop at the first occurrance. This is a bit
-	// tricky in order to make typical typing work conveniently. The purpose of applying quotes
-	// is to preserve the values when splitting them back apart. That is CatenateContainerItems
-	// and SeparateContainerItems must round trip properly. For the most part we only look for
-	// separators here. Internal quotes, as in -- Irving "Bud" Jones -- won't cause problems in
-	// the separation. An initial quote will though, it will make the value look quoted.
-
-	charOffset = 0;
-	ClassifyCharacter ( item->c_str(), charOffset, &charKind, &charLen, &uniChar );
-	
-	if ( charKind != UCK_quote ) {
-	
-	for ( charOffset = 0; size_t(charOffset) < item->size(); charOffset += charLen ) {
-
-			ClassifyCharacter ( item->c_str(), charOffset, &charKind, &charLen, &uniChar );
-
-			if ( charKind == UCK_space ) {
-				if ( prevSpace ) break; // Multiple spaces are a separator.
-				prevSpace = true;
-			} else {
-				prevSpace = false;
-				if ( (charKind == UCK_semicolon) || (charKind == UCK_control) ) break;
-				if ( (charKind == UCK_comma) && (! allowCommas) ) break;
-			}
-
-		}
-	
-	}
-	
-	if ( size_t(charOffset) < item->size() ) {
-	
-		// --------------------------------------------------------------------------------------
-		// Create a quoted copy, doubling any internal quotes that match the outer ones. Internal
-		// quotes did not stop the "needs quoting" search, but they do need doubling. So we have
-		// to rescan the front of the string for quotes. Handle the special case of U+301D being
-		// closed by either U+301E or U+301F.
-		
-		XMP_VarString	newItem;
-		size_t			splitPoint;
-		
-		for ( splitPoint = 0; splitPoint <= charOffset; ++splitPoint ) {
-			ClassifyCharacter ( item->c_str(), splitPoint, &charKind, &charLen, &uniChar );
-			if ( charKind == UCK_quote ) break;
-		}
-		
-		CodePointToUTF8 ( openQuote, newItem );
-		newItem.append ( *item, 0, splitPoint );	// Copy the leading "normal" portion.
-
-		for ( charOffset = splitPoint; size_t(charOffset) < item->size(); charOffset += charLen ) {
-			ClassifyCharacter ( item->c_str(), charOffset, &charKind, &charLen, &uniChar );
-			newItem.append ( *item, charOffset, charLen );
-			if ( (charKind == UCK_quote) && IsSurroundingQuote ( uniChar, openQuote, closeQuote ) ) {
-				newItem.append ( *item, charOffset, charLen );
-			}
-		}
-		
-		XMP_VarString closeStr;
-		CodePointToUTF8 ( closeQuote, closeStr );
-		newItem.append ( closeStr );
-		
-		*item = newItem;
-	
-	}
-	
-}	// ApplyQuotes
-
-
-// -------------------------------------------------------------------------------------------------
-// IsInternalProperty
-// ------------------
-
-// *** Need static checks of the schema prefixes!
-
-#define IsExternalProperty(s,p) (! IsInternalProperty ( s, p ))
-
-static bool
-IsInternalProperty ( const XMP_VarString & schema, const XMP_VarString & prop )
-{
-	bool isInternal = false;
-
-	if ( schema == kXMP_NS_DC ) {
-	
-		if ( (prop == "dc:format")	||
-			 (prop == "dc:language") ) {
-			isInternal = true;
-		}
-	
-	} else if ( schema == kXMP_NS_XMP ) {
-	
-		if ( (prop == "xmp:BaseURL")		||
-			 (prop == "xmp:CreatorTool")	||
-			 (prop == "xmp:Format")			||
-			 (prop == "xmp:Locale")			||
-			 (prop == "xmp:MetadataDate")	||
-			 (prop == "xmp:ModifyDate") ) {
-			isInternal = true;
-		}
-	
-	} else if ( schema == kXMP_NS_PDF ) {
-	
-		if ( (prop == "pdf:BaseURL")	||
-			 (prop == "pdf:Creator")	||
-			 (prop == "pdf:ModDate")	||
-			 (prop == "pdf:PDFVersion") ||
-			 (prop == "pdf:Producer") ) {
-			isInternal = true;
-		}
-	
-	} else if ( schema == kXMP_NS_TIFF ) {
-		
-		isInternal = true;	// ! The TIFF properties are internal by default.
-		if ( (prop == "tiff:ImageDescription")	||	// ! ImageDescription, Artist, and Copyright are aliased.
-			 (prop == "tiff:Artist")			||
-			 (prop == "tiff:Copyright") ) {
-			isInternal = false;
-		}
-
-	} else if ( schema == kXMP_NS_EXIF ) {
-	
-		isInternal = true;	// ! The EXIF properties are internal by default.
-		if ( prop == "exif:UserComment" ) isInternal = false;
-
-	} else if ( schema == kXMP_NS_EXIF_Aux ) {
-	
-		isInternal = true;	// ! The EXIF Aux properties are internal by default.
-	
-	} else if ( schema == kXMP_NS_Photoshop ) {
-	
-		if ( prop == "photoshop:ICCProfile" ) isInternal = true;
-	
-	} else if ( schema == kXMP_NS_CameraRaw ) {
-	
-		if ( (prop == "crs:Version")		||
-			 (prop == "crs:RawFileName")	||
-			 (prop == "crs:ToneCurveName") ) {
-			isInternal = true;
-		}
-	
-	} else if ( schema == kXMP_NS_AdobeStockPhoto ) {
-	
-		isInternal = true;	// ! The bmsp schema has only internal properties.
-
-	} else if ( schema == kXMP_NS_XMP_MM ) {
-	
-		isInternal = true;	// ! The xmpMM schema has only internal properties.
-	
-	} else if ( schema == kXMP_NS_XMP_Text ) {
-	
-		isInternal = true;	// ! The xmpT schema has only internal properties.
-	
-	} else if ( schema == kXMP_NS_XMP_PagedFile ) {
-	
-		isInternal = true;	// ! The xmpTPg schema has only internal properties.
-	
-	} else if ( schema == kXMP_NS_XMP_Graphics ) {
-	
-		isInternal = true;	// ! The xmpG schema has only internal properties.
-	
-	} else if ( schema == kXMP_NS_XMP_Image ) {
-	
-		isInternal = true;	// ! The xmpGImg schema has only internal properties.
-	
-	} else if ( schema == kXMP_NS_XMP_Font ) {
-	
-		isInternal = true;	// ! The stFNT schema has only internal properties.
-	
-	}
-	
-	return isInternal;
-
-}	// IsInternalProperty
-
-
-// -------------------------------------------------------------------------------------------------
-// RemoveSchemaChildren
-// --------------------
-
-static void
-RemoveSchemaChildren ( XMP_NodePtrPos schemaPos, bool doAll )
-{
-	XMP_Node * schemaNode = *schemaPos;
-	XMP_Assert ( XMP_NodeIsSchema ( schemaNode->options ) );
-		
-	// ! Iterate backwards to reduce shuffling as children are erased and to simplify the logic for
-	// ! denoting the current child. (Erasing child n makes the old n+1 now be n.)
-
-	size_t		   propCount = schemaNode->children.size();
-	XMP_NodePtrPos beginPos	 = schemaNode->children.begin();
-	
-	for ( size_t propNum = propCount-1, propLim = (size_t)(-1); propNum != propLim; --propNum ) {
-		XMP_NodePtrPos currProp = beginPos + propNum;
-		if ( doAll || IsExternalProperty ( schemaNode->name, (*currProp)->name ) ) {
-			delete *currProp;	// ! Both delete the node and erase the pointer from the parent.
-			schemaNode->children.erase ( currProp );
-		}
-	}
-	
-	if ( schemaNode->children.empty() ) {
-		XMP_Node * tree = schemaNode->parent;
-		tree->children.erase ( schemaPos );
-		delete schemaNode;
-	}
-
-}	// RemoveSchemaChildren
-
-
-// -------------------------------------------------------------------------------------------------
-// ItemValuesMatch
-// ---------------
-//
-// Does the value comparisons for array merging as part of XMPUtils::AppendProperties.
-
-static bool
-ItemValuesMatch ( const XMP_Node * leftNode, const XMP_Node * rightNode )
-{
-	const XMP_OptionBits leftForm  = leftNode->options & kXMP_PropCompositeMask;
-	const XMP_OptionBits rightForm = leftNode->options & kXMP_PropCompositeMask;
-	
-	if ( leftForm != rightForm ) return false;
-	
-	if ( leftForm == 0 ) {
-	
-		// Simple nodes, check the values and xml:lang qualifiers.
-		
-		if ( leftNode->value != rightNode->value ) return false;
-		if ( (leftNode->options & kXMP_PropHasLang) != (rightNode->options & kXMP_PropHasLang) ) return false;
-		if ( leftNode->options & kXMP_PropHasLang ) {
-			if ( leftNode->qualifiers[0]->value != rightNode->qualifiers[0]->value ) return false;
-		}
-	
-	} else if ( leftForm == kXMP_PropValueIsStruct ) {
-	
-		// Struct nodes, see if all fields match, ignoring order.
-		
-		if ( leftNode->children.size() != rightNode->children.size() ) return false;
-
-		for ( size_t leftNum = 0, leftLim = leftNode->children.size(); leftNum != leftLim; ++leftNum ) {
-			const XMP_Node * leftField	= leftNode->children[leftNum];
-			const XMP_Node * rightField = FindConstChild ( rightNode, leftField->name.c_str() );
-			if ( (rightField == 0) || (! ItemValuesMatch ( leftField, rightField )) ) return false;
-		}
-		
-	} else {
-	
-		// Array nodes, see if the "leftNode" values are present in the "rightNode", ignoring order, duplicates,
-		// and extra values in the rightNode-> The rightNode is the destination for AppendProperties.
-
-		XMP_Assert ( leftForm & kXMP_PropValueIsArray );
-		
-		for ( size_t leftNum = 0, leftLim = leftNode->children.size(); leftNum != leftLim; ++leftNum ) {
-
-			const XMP_Node * leftItem = leftNode->children[leftNum];
-
-			size_t rightNum, rightLim;
-			for ( rightNum = 0, rightLim = rightNode->children.size(); rightNum != rightLim; ++rightNum ) {
-				const XMP_Node * rightItem = rightNode->children[rightNum];
-				if ( ItemValuesMatch ( leftItem, rightItem ) ) break;
-			}
-			if ( rightNum == rightLim ) return false;
-
-		}
-	
-	}
-
-	return true;	// All of the checks passed.
-	
-}	// ItemValuesMatch
-
-
-// -------------------------------------------------------------------------------------------------
-// AppendSubtree
-// -------------
-//
-// The main implementation of XMPUtils::AppendProperties. See the description in TXMPMeta.hpp.
-
-static void
-AppendSubtree ( const XMP_Node * sourceNode, XMP_Node * destParent, const bool replaceOld, const bool deleteEmpty )
-{
-	XMP_NodePtrPos destPos;
-	XMP_Node * destNode = FindChildNode ( destParent, sourceNode->name.c_str(), kXMP_ExistingOnly, &destPos );
-	
-	bool valueIsEmpty = false;
-	if ( deleteEmpty ) {
-		if ( XMP_PropIsSimple ( sourceNode->options ) ) {
-			valueIsEmpty = sourceNode->value.empty();
-		} else {
-			valueIsEmpty = sourceNode->children.empty();
-		} 
-	}
-	
-	if ( deleteEmpty & valueIsEmpty ) {
-	
-		if ( destNode != 0 ) {
-			delete ( destNode );
-			destParent->children.erase ( destPos );
-		}
-	
-	} else if ( destNode == 0 ) {
-	
-		// The one easy case, the destination does not exist.
-		CloneSubtree ( sourceNode, destParent );
-
-	} else if ( replaceOld ) {
-	
-		// The destination exists and should be replaced.
-
-		destNode->value	  = sourceNode->value;	// *** Should use SetNode.
-		destNode->options = sourceNode->options;
-		destNode->RemoveChildren();
-		destNode->RemoveQualifiers();
-		CloneOffspring ( sourceNode, destNode );
-
-		#if 0	// *** XMP_DebugBuild
-			destNode->_valuePtr = destNode->value.c_str();
-		#endif
-	
-	} else {
-
-		// The destination exists and is not totally replaced. Structs and arrays are merged.
-
-		XMP_OptionBits sourceForm = sourceNode->options & kXMP_PropCompositeMask;
-		XMP_OptionBits destForm	  = destNode->options & kXMP_PropCompositeMask;
-		if ( sourceForm != destForm ) return;
-		
-		if ( sourceForm == kXMP_PropValueIsStruct ) {
-		
-			// To merge a struct process the fields recursively. E.g. add simple missing fields. The
-			// recursive call to AppendSubtree will handle deletion for fields with empty values.
-
-			for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) {
-				const XMP_Node * sourceField = sourceNode->children[sourceNum];
-				AppendSubtree ( sourceField, destNode, replaceOld, deleteEmpty );
-				if ( deleteEmpty && destNode->children.empty() ) {
-					delete ( destNode );
-					destParent->children.erase ( destPos );
-				}
-			}
-			
-		} else if ( sourceForm & kXMP_PropArrayIsAltText ) {
-		
-			// Merge AltText arrays by the xml:lang qualifiers. Make sure x-default is first. Make a
-			// special check for deletion of empty values. Meaningful in AltText arrays because the
-			// xml:lang qualifier provides unambiguous source/dest correspondence.
-
-			for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) {
-
-				const XMP_Node * sourceItem = sourceNode->children[sourceNum];
-				if ( sourceItem->qualifiers.empty() || (sourceItem->qualifiers[0]->name != "xml:lang") ) continue;
-				
-				XMP_Index  destIndex = LookupLangItem ( destNode, sourceItem->qualifiers[0]->value );
-				
-				if ( deleteEmpty && sourceItem->value.empty() ) {
-
-					if ( destIndex != -1 ) {
-						delete ( destNode->children[destIndex] );
-						destNode->children.erase ( destNode->children.begin() + destIndex );
-						if ( destNode->children.empty() ) {
-							delete ( destNode );
-							destParent->children.erase ( destPos );
-						}
-					}
-
-				} else {
-				
-					if (  destIndex != -1 ) continue;	// Not replacing, keep the existing item.
-				
-					if ( (sourceItem->qualifiers[0]->value != "x-default") || destNode->children.empty() ) {
-						CloneSubtree ( sourceItem, destNode );
-					} else {
-						XMP_Node * destItem = new XMP_Node ( destNode, sourceItem->name, sourceItem->value, sourceItem->options );
-						CloneOffspring ( sourceItem, destItem );
-						destNode->children.insert ( destNode->children.begin(), destItem );
-				}
-				
-				}
-
-			}
-		
-		} else if ( sourceForm & kXMP_PropValueIsArray ) {
-		
-			// Merge other arrays by item values. Don't worry about order or duplicates. Source 
-			// items with empty values do not cause deletion, that conflicts horribly with merging.
-
-			for ( size_t sourceNum = 0, sourceLim = sourceNode->children.size(); sourceNum != sourceLim; ++sourceNum ) {
-				const XMP_Node * sourceItem = sourceNode->children[sourceNum];
-
-				size_t	destNum, destLim;
-				for ( destNum = 0, destLim = destNode->children.size(); destNum != destLim; ++destNum ) {
-					const XMP_Node * destItem = destNode->children[destNum];
-					if ( ItemValuesMatch ( sourceItem, destItem ) ) break;
-				}
-				if ( destNum == destLim ) CloneSubtree ( sourceItem, destNode );
-
-			}
-			
-		}
-
-	}
-
-}	// AppendSubtree
-
-
-// =================================================================================================
-// Class Static Functions
-// ======================
-
-// -------------------------------------------------------------------------------------------------
-// CatenateArrayItems
-// ------------------
-
-/* class static */ void
-XMPUtils::CatenateArrayItems ( const XMPMeta & xmpObj,
-							   XMP_StringPtr   schemaNS,
-							   XMP_StringPtr   arrayName,
-							   XMP_StringPtr   separator,
-							   XMP_StringPtr   quotes,
-							   XMP_OptionBits  options,
-							   XMP_StringPtr * catedStr,
-							   XMP_StringLen * catedLen )
-{
-	XMP_Assert ( (schemaNS != 0) && (arrayName != 0) ); // ! Enforced by wrapper.
-	XMP_Assert ( (separator != 0) && (quotes != 0) && (catedStr != 0) && (catedLen != 0) ); // ! Enforced by wrapper.
-	
-	size_t		 strLen, strPos, charLen;
-	UniCharKind	 charKind;
-	UniCodePoint currUCP, openQuote, closeQuote;
-	
-	const bool allowCommas = ((options & kXMPUtil_AllowCommas) != 0);
-	
-	const XMP_Node * arrayNode = 0; // ! Move up to avoid gcc complaints.
-	XMP_OptionBits	 arrayForm = 0;
-	const XMP_Node * currItem  = 0;
-
-	// Make sure the separator is OK. It must be one semicolon surrounded by zero or more spaces.
-	// Any of the recognized semicolons or spaces are allowed.
-	
-	strPos = 0;
-	strLen = strlen ( separator );
-	bool haveSemicolon = false;
-	
-	while ( strPos < strLen ) {
-		ClassifyCharacter ( separator, strPos, &charKind, &charLen, &currUCP );
-		strPos += charLen;
-		if ( charKind == UCK_semicolon ) {
-			if ( haveSemicolon ) XMP_Throw ( "Separator can have only one semicolon",  kXMPErr_BadParam );
-			haveSemicolon = true;
-		} else if ( charKind != UCK_space ) {
-			XMP_Throw ( "Separator can have only spaces and one semicolon",	 kXMPErr_BadParam );
-		}
-	};
-	if ( ! haveSemicolon ) XMP_Throw ( "Separator must have one semicolon",	 kXMPErr_BadParam );
-	
-	// Make sure the open and close quotes are a legitimate pair.
-
-	strLen = strlen ( quotes );
-	ClassifyCharacter ( quotes, 0, &charKind, &charLen, &openQuote );
-	if ( charKind != UCK_quote ) XMP_Throw ( "Invalid quoting character", kXMPErr_BadParam );
-
-	if ( charLen == strLen ) {
-		closeQuote = openQuote;
-	} else {
-		strPos = charLen;
-		ClassifyCharacter ( quotes, strPos, &charKind, &charLen, &closeQuote );
-		if ( charKind != UCK_quote ) XMP_Throw ( "Invalid quoting character", kXMPErr_BadParam );
-		if ( (strPos + charLen) != strLen ) XMP_Throw ( "Quoting string too long", kXMPErr_BadParam );
-	}
-	if ( closeQuote != GetClosingQuote ( openQuote ) ) XMP_Throw ( "Mismatched quote pair", kXMPErr_BadParam );
-
-	// Return an empty result if the array does not exist, hurl if it isn't the right form.
-	
-	sCatenatedItems->erase();
-
-	XMP_ExpandedXPath arrayPath;
-	ExpandXPath ( schemaNS, arrayName, &arrayPath );
-
-	arrayNode = FindConstNode ( &xmpObj.tree, arrayPath );
-	if ( arrayNode == 0 ) goto EXIT;	// ! Need to set the output pointer and length.
-
-	arrayForm = arrayNode->options & kXMP_PropCompositeMask;
-	if ( (! (arrayForm & kXMP_PropValueIsArray)) || (arrayForm & kXMP_PropArrayIsAlternate) ) {
-		XMP_Throw ( "Named property must be non-alternate array", kXMPErr_BadParam );
-	}
-	if ( arrayNode->children.empty() ) goto EXIT;	// ! Need to set the output pointer and length.
-	
-	// Build the result, quoting the array items, adding separators. Hurl if any item isn't simple.
-	// Start the result with the first value, then add the rest with a preceding separator.
-	
-	currItem = arrayNode->children[0];
-	
-	if ( (currItem->options & kXMP_PropCompositeMask) != 0 ) XMP_Throw ( "Array items must be simple", kXMPErr_BadParam );
-	*sCatenatedItems = currItem->value;
-	ApplyQuotes ( sCatenatedItems, openQuote, closeQuote, allowCommas );
-	
-	for ( size_t itemNum = 1, itemLim = arrayNode->children.size(); itemNum != itemLim; ++itemNum ) {
-		const XMP_Node * currItem = arrayNode->children[itemNum];
-		if ( (currItem->options & kXMP_PropCompositeMask) != 0 ) XMP_Throw ( "Array items must be simple", kXMPErr_BadParam );
-		XMP_VarString tempStr ( currItem->value );
-		ApplyQuotes ( &tempStr, openQuote, closeQuote, allowCommas );
-		*sCatenatedItems += separator;
-		*sCatenatedItems += tempStr;
-	}
-	
-EXIT:
-	*catedStr = sCatenatedItems->c_str();
-	*catedLen = sCatenatedItems->size();
-
-}	// CatenateArrayItems
-
-
-// -------------------------------------------------------------------------------------------------
-// SeparateArrayItems
-// ------------------
-
-/* class static */ void
-XMPUtils::SeparateArrayItems ( XMPMeta *	  xmpObj,
-							   XMP_StringPtr  schemaNS,
-							   XMP_StringPtr  arrayName,
-							   XMP_OptionBits options,
-							   XMP_StringPtr  catedStr )
-{
-	XMP_Assert ( (schemaNS != 0) && (arrayName != 0) && (catedStr != 0) );	// ! Enforced by wrapper.
-	
-	XMP_VarString itemValue;
-	size_t itemStart, itemEnd;
-	size_t nextSize, charSize = 0;	// Avoid VS uninit var warnings.
-	UniCharKind	  nextKind, charKind = UCK_normal;
-	UniCodePoint  nextChar, uniChar = 0;
-	
-	// Extract "special" option bits, verify and normalize the others.
-	
-	bool preserveCommas = false;
-	if ( options & kXMPUtil_AllowCommas ) {
-		preserveCommas = true;
-		options ^= kXMPUtil_AllowCommas;
-	}
-
-	options = VerifySetOptions ( options, 0 );	// Keep a zero value, has special meaning below.
-	if ( options & ~kXMP_PropArrayFormMask ) XMP_Throw ( "Options can only provide array form", kXMPErr_BadOptions );
-	
-	// Find the array node, make sure it is OK. Move the current children aside, to be readded later if kept.
-	
-	XMP_ExpandedXPath arrayPath;
-	ExpandXPath ( schemaNS, arrayName, &arrayPath );
-	XMP_Node * arrayNode = FindNode ( &xmpObj->tree, arrayPath, kXMP_ExistingOnly );
-	
-	if ( arrayNode != 0 ) {
-		// The array exists, make sure the form is compatible. Zero arrayForm means take what exists.
-		XMP_OptionBits arrayForm = arrayNode->options & kXMP_PropArrayFormMask;
-		if ( (arrayForm == 0) || (arrayForm & kXMP_PropArrayIsAlternate) ) {
-			XMP_Throw ( "Named property must be non-alternate array", kXMPErr_BadXPath );
-		}
-		if ( (options != 0) && (options != arrayForm) ) XMP_Throw ( "Mismatch of specified and existing array form", kXMPErr_BadXPath );	// *** Right error?
-	} else {
-		// The array does not exist, try to create it.
-		arrayNode = FindNode ( &xmpObj->tree, arrayPath, kXMP_CreateNodes, (options | kXMP_PropValueIsArray) );
-		if ( arrayNode == 0 ) XMP_Throw ( "Failed to create named array", kXMPErr_BadXPath );
-	}
-
-	XMP_NodeOffspring oldChildren ( arrayNode->children );
-	size_t oldChildCount = oldChildren.size();
-	arrayNode->children.clear();
-	
-	// Extract the item values one at a time, until the whole input string is done. Be very careful
-	// in the extraction about the string positions. They are essentially byte pointers, while the
-	// contents are UTF-8. Adding or subtracting 1 does not necessarily move 1 Unicode character!
-	
-	size_t endPos = strlen ( catedStr );
-	
-	itemEnd = 0;
-	while ( itemEnd < endPos ) {
-		
-		// Skip any leading spaces and separation characters. Always skip commas here. They can be
-		// kept when within a value, but not when alone between values.
-		
-		for ( itemStart = itemEnd; itemStart < endPos; itemStart += charSize ) {
-			ClassifyCharacter ( catedStr, itemStart, &charKind, &charSize, &uniChar );
-			if ( (charKind == UCK_normal) || (charKind == UCK_quote) ) break;
-		}
-		if ( itemStart >= endPos ) break;
-		
-		if ( charKind != UCK_quote ) {
-		
-			// This is not a quoted value. Scan for the end, create an array item from the substring.
-
-			for ( itemEnd = itemStart; itemEnd < endPos; itemEnd += charSize ) {
-
-				ClassifyCharacter ( catedStr, itemEnd, &charKind, &charSize, &uniChar );
-
-				if ( (charKind == UCK_normal) || (charKind == UCK_quote) ) continue;
-				if ( (charKind == UCK_comma) && preserveCommas ) continue;
-				if ( charKind != UCK_space ) break;
-
-				if ( (itemEnd + charSize) >= endPos ) break;	// Anything left?
-				ClassifyCharacter ( catedStr, (itemEnd+charSize), &nextKind, &nextSize, &nextChar );
-				if ( (nextKind == UCK_normal) || (nextKind == UCK_quote) ) continue;
-				if ( (nextKind == UCK_comma) && preserveCommas ) continue;
-				break;	// Have multiple spaces, or a space followed by a separator.
-
-			}		
-
-			itemValue.assign ( catedStr, itemStart, (itemEnd - itemStart) );
-		
-		} else {
-		
-			// Accumulate quoted values into a local string, undoubling internal quotes that
-			// match the surrounding quotes. Do not undouble "unmatching" quotes.
-		
-			UniCodePoint openQuote = uniChar;
-			UniCodePoint closeQuote = GetClosingQuote ( openQuote );
-
-			itemStart += charSize;	// Skip the opening quote;
-			itemValue.erase();
-			
-			for ( itemEnd = itemStart; itemEnd < endPos; itemEnd += charSize ) {
-
-				ClassifyCharacter ( catedStr, itemEnd, &charKind, &charSize, &uniChar );
-
-				if ( (charKind != UCK_quote) || (! IsSurroundingQuote ( uniChar, openQuote, closeQuote)) ) {
-				
-					// This is not a matching quote, just append it to the item value.
-					itemValue.append ( catedStr, itemEnd, charSize );
-					
-				} else {
-				
-					// This is a "matching" quote. Is it doubled, or the final closing quote? Tolerate
-					// various edge cases like undoubled opening (non-closing) quotes, or end of input.
-					
-					if ( (itemEnd + charSize) < endPos ) {
-						ClassifyCharacter ( catedStr, itemEnd+charSize, &nextKind, &nextSize, &nextChar );
-					} else {
-						nextKind = UCK_semicolon; nextSize = 0; nextChar = 0x3B;
-					}
-					
-					if ( uniChar == nextChar ) {
-						// This is doubled, copy it and skip the double.
-						itemValue.append ( catedStr, itemEnd, charSize );
-						itemEnd += nextSize;	// Loop will add in charSize.
-					} else if ( ! IsClosingingQuote ( uniChar, openQuote, closeQuote ) ) {
-						// This is an undoubled, non-closing quote, copy it.
-						itemValue.append ( catedStr, itemEnd, charSize );
-					} else {
-						// This is an undoubled closing quote, skip it and exit the loop.
-						itemEnd += charSize;
-						break;
-					}
-
-				}
-
-			}	// Loop to accumulate the quoted value.
-		
-		}
-
-		// Add the separated item to the array. Keep a matching old value in case it had separators.
-		
-		size_t oldChild;
-		for ( oldChild = 0; oldChild < oldChildCount; ++oldChild ) {
-			if ( (oldChildren[oldChild] != 0) && (itemValue == oldChildren[oldChild]->value) ) break;
-		}
-		
-		XMP_Node * newItem = 0;
-		if ( oldChild == oldChildCount ) {
-			newItem = new XMP_Node ( arrayNode, kXMP_ArrayItemName, itemValue.c_str(), 0 );
-		} else {
-			newItem = oldChildren[oldChild];
-			oldChildren[oldChild] = 0;	// ! Don't match again, let duplicates be seen.
-		}
-		arrayNode->children.push_back ( newItem );
-		
-	}	// Loop through all of the returned items.
-
-	// Delete any of the old children that were not kept.
-	for ( size_t i = 0; i < oldChildCount; ++i ) {
-		if ( oldChildren[i] != 0 ) delete oldChildren[i];
-	}
-	
-}	// SeparateArrayItems
-
-
-// -------------------------------------------------------------------------------------------------
-// RemoveProperties
-// ----------------
-
-/* class static */ void
-XMPUtils::RemoveProperties ( XMPMeta *		xmpObj,
-							 XMP_StringPtr	schemaNS,
-							 XMP_StringPtr	propName,
-							 XMP_OptionBits options )
-{
-	XMP_Assert ( (schemaNS != 0) && (propName != 0) );	// ! Enforced by wrapper.
-	
-	const bool doAll = XMP_TestOption (options, kXMPUtil_DoAllProperties );
-	const bool includeAliases = XMP_TestOption ( options, kXMPUtil_IncludeAliases );
-	
-	if ( *propName != 0 ) {
-	
-		// Remove just the one indicated property. This might be an alias, the named schema might
-		// not actually exist. So don't lookup the schema node.
-		
-		if ( *schemaNS == 0 ) XMP_Throw ( "Property name requires schema namespace", kXMPErr_BadParam );
-		
-		XMP_ExpandedXPath expPath;
-		ExpandXPath ( schemaNS, propName, &expPath );
-		
-		XMP_NodePtrPos propPos;
-		XMP_Node * propNode = FindNode ( &(xmpObj->tree), expPath, kXMP_ExistingOnly, kXMP_NoOptions, &propPos );
-		if ( propNode != 0 ) {
-			if ( doAll || IsExternalProperty ( expPath[kSchemaStep].step, expPath[kRootPropStep].step ) ) {
-				XMP_Node * parent = propNode->parent;	// *** Should have XMP_Node::RemoveChild(pos).
-				delete propNode;	// ! Both delete the node and erase the pointer from the parent.
-				parent->children.erase ( propPos );
-				DeleteEmptySchema ( parent );
-			}
-		}
-	
-	} else if ( *schemaNS != 0 ) {
-	
-		// Remove all properties from the named schema. Optionally include aliases, in which case
-		// there might not be an actual schema node. 
-
-		XMP_NodePtrPos schemaPos;
-		XMP_Node * schemaNode = FindSchemaNode ( &xmpObj->tree, schemaNS, kXMP_ExistingOnly, &schemaPos );
-		if ( schemaNode != 0 ) RemoveSchemaChildren ( schemaPos, doAll );
-		
-		if ( includeAliases ) {
-		
-			// We're removing the aliases also. Look them up by their namespace prefix. Yes, the
-			// alias map is sorted so we could process just that portion. But that takes more code
-			// and the extra speed isn't worth it. (Plus this way we avoid a dependence on the map
-			// implementation.) Lookup the XMP node from the alias, to make sure the actual exists.
-
-			XMP_StringPtr nsPrefix;
-			XMP_StringLen nsLen;
-			(void) XMPMeta::GetNamespacePrefix ( schemaNS, &nsPrefix, &nsLen );
-			
-			XMP_AliasMapPos currAlias = sRegisteredAliasMap->begin();
-			XMP_AliasMapPos endAlias  = sRegisteredAliasMap->end();
-			
-			for ( ; currAlias != endAlias; ++currAlias ) {
-				if ( strncmp ( currAlias->first.c_str(), nsPrefix, nsLen ) == 0 ) {
-					XMP_NodePtrPos actualPos;
-					XMP_Node * actualProp = FindNode ( &xmpObj->tree, currAlias->second, kXMP_ExistingOnly, kXMP_NoOptions, &actualPos );
-					if ( actualProp != 0 ) {
-						XMP_Node * rootProp = actualProp;
-						while ( ! XMP_NodeIsSchema ( rootProp->parent->options ) ) rootProp = rootProp->parent;
-						if ( doAll || IsExternalProperty ( rootProp->parent->name, rootProp->name ) ) {
-							XMP_Node * parent = actualProp->parent;
-							delete actualProp;	// ! Both delete the node and erase the pointer from the parent.
-							parent->children.erase ( actualPos );
-							DeleteEmptySchema ( parent );
-						}
-					}
-				}
-			}
-
-		}
-
-	} else {
-		
-		// Remove all appropriate properties from all schema. In this case we don't have to be
-		// concerned with aliases, they are handled implicitly from the actual properties.
-
-		// ! Iterate backwards to reduce shuffling if schema are erased and to simplify the logic
-		// ! for denoting the current schema. (Erasing schema n makes the old n+1 now be n.)
-
-		size_t		   schemaCount = xmpObj->tree.children.size();
-		XMP_NodePtrPos beginPos	   = xmpObj->tree.children.begin();
-		
-		for ( size_t schemaNum = schemaCount-1, schemaLim = (size_t)(-1); schemaNum != schemaLim; --schemaNum ) {
-			XMP_NodePtrPos currSchema = beginPos + schemaNum;
-			RemoveSchemaChildren ( currSchema, doAll );
-		}
-	
-	}
-
-}	// RemoveProperties
-
-
-// -------------------------------------------------------------------------------------------------
-// AppendProperties
-// ----------------
-
-/* class static */ void
-XMPUtils::AppendProperties ( const XMPMeta & source,
-							 XMPMeta *		 dest,
-							 XMP_OptionBits	 options )
-{
-	XMP_Assert ( dest != 0 );	// ! Enforced by wrapper.
-
-	const bool doAll	   = ((options & kXMPUtil_DoAllProperties) != 0);
-	const bool replaceOld  = ((options & kXMPUtil_ReplaceOldValues) != 0);
-	const bool deleteEmpty = ((options & kXMPUtil_DeleteEmptyValues) != 0);
-
-	for ( size_t schemaNum = 0, schemaLim = source.tree.children.size(); schemaNum != schemaLim; ++schemaNum ) {
-
-		const XMP_Node * sourceSchema = source.tree.children[schemaNum];
-
-		// Make sure we have a destination schema node. Remember if it is newly created.
-		
-		XMP_Node * destSchema = FindSchemaNode ( &dest->tree, sourceSchema->name.c_str(), kXMP_ExistingOnly );
-		const bool newDestSchema = (destSchema == 0);
-		if ( newDestSchema ) {
-			destSchema = new XMP_Node ( &dest->tree, sourceSchema->name, sourceSchema->value, kXMP_SchemaNode );
-			dest->tree.children.push_back ( destSchema );
-		}
-
-		// Process the source schema's children. Do this backwards in case deleteEmpty is set.
-		
-		for ( long propNum = ((long)sourceSchema->children.size() - 1); propNum >= 0; --propNum ) {
-			const XMP_Node * sourceProp = sourceSchema->children[propNum];
-			if ( doAll || IsExternalProperty ( sourceSchema->name, sourceProp->name ) ) {
-				AppendSubtree ( sourceProp, destSchema, replaceOld, deleteEmpty );
-// ***				RemoveMultiValueInfo ( dest, sourceSchema->name.c_str(), sourceProp->name.c_str() );
-			}
-		}
-		
-		if ( destSchema->children.empty() ) {
-			if ( newDestSchema ) {
-				delete ( destSchema );
-				dest->tree.children.pop_back();
-			} else if ( deleteEmpty ) {
-				DeleteEmptySchema ( destSchema );
-			}
-		}
-		
-	}
-
-}	// AppendProperties
-
-
-// -------------------------------------------------------------------------------------------------
-// DuplicateSubtree
-// ----------------
-
-/* class static */ void
-XMPUtils::DuplicateSubtree ( const XMPMeta & source,
-							 XMPMeta *		 dest,
-							 XMP_StringPtr	 sourceNS,
-							 XMP_StringPtr	 sourceRoot,
-							 XMP_StringPtr	 destNS,
-							 XMP_StringPtr	 destRoot,
-							 XMP_OptionBits	 options )
-{
-	UNUSED(options);
-	
-	bool fullSourceTree = false;
-	bool fullDestTree   = false;
-	
-	XMP_ExpandedXPath sourcePath, destPath; 
-
-	const XMP_Node * sourceNode = 0;
-	XMP_Node * destNode = 0;
-	
-	XMP_Assert ( (sourceNS != 0) && (*sourceNS != 0) );
-	XMP_Assert ( (sourceRoot != 0) && (*sourceRoot != 0) );
-	XMP_Assert ( (dest != 0) && (destNS != 0) && (destRoot != 0) );
-
-	if ( *destNS == 0 )	  destNS   = sourceNS;
-	if ( *destRoot == 0 ) destRoot = sourceRoot;
-	
-	if ( XMP_LitMatch ( sourceNS, "*" ) ) fullSourceTree = true;
-	if ( XMP_LitMatch ( destNS, "*" ) )   fullDestTree   = true;
-	
-	if ( (&source == dest) && (fullSourceTree | fullDestTree) ) {
-		XMP_Throw ( "Can't duplicate tree onto itself", kXMPErr_BadParam );
-	}
-	
-	if ( fullSourceTree & fullDestTree ) XMP_Throw ( "Use Clone for full tree to full tree", kXMPErr_BadParam );
-
-	if ( fullSourceTree ) {
-	
-		// The destination must be an existing empty struct, copy all of the source top level as fields.
-
-		ExpandXPath ( destNS, destRoot, &destPath );
-		destNode = FindNode ( &dest->tree, destPath, kXMP_ExistingOnly );
-
-		if ( (destNode == 0) || (! XMP_PropIsStruct ( destNode->options )) ) {
-			XMP_Throw ( "Destination must be an existing struct", kXMPErr_BadXPath );
-		}
-		
-		if ( ! destNode->children.empty() ) {
-			if ( options & kXMP_DeleteExisting ) {
-				destNode->RemoveChildren();
-			} else {
-				XMP_Throw ( "Destination must be an empty struct", kXMPErr_BadXPath );
-			}
-		}
-		
-		for ( size_t schemaNum = 0, schemaLim = source.tree.children.size(); schemaNum < schemaLim; ++schemaNum ) {
-
-			const XMP_Node * currSchema = source.tree.children[schemaNum];
-
-			for ( size_t propNum = 0, propLim = currSchema->children.size(); propNum < propLim; ++propNum ) {
-				sourceNode = currSchema->children[propNum];
-				XMP_Node * copyNode = new XMP_Node ( destNode, sourceNode->name, sourceNode->value, sourceNode->options );
-				destNode->children.push_back ( copyNode );
-				CloneOffspring ( sourceNode, copyNode );
-			}
-
-		}
-	
-	} else if ( fullDestTree ) {
-
-		// The source node must be an existing struct, copy all of the fields to the dest top level.
-
-		XMP_ExpandedXPath sourcePath; 
-		ExpandXPath ( sourceNS, sourceRoot, &sourcePath );
-		sourceNode = FindConstNode ( &source.tree, sourcePath );
-
-		if ( (sourceNode == 0) || (! XMP_PropIsStruct ( sourceNode->options )) ) {
-			XMP_Throw ( "Source must be an existing struct", kXMPErr_BadXPath );
-		}
-		
-		destNode = &dest->tree;
-		
-		if ( ! destNode->children.empty() ) {
-			if ( options & kXMP_DeleteExisting ) {
-				destNode->RemoveChildren();
-			} else {
-				XMP_Throw ( "Destination tree must be empty", kXMPErr_BadXPath );
-			}
-		}
-		
-		std::string   nsPrefix;
-		XMP_StringPtr nsURI;
-		XMP_StringLen nsLen;
-		
-		for ( size_t fieldNum = 0, fieldLim = sourceNode->children.size(); fieldNum < fieldLim; ++fieldNum ) {
-
-			const XMP_Node * currField = sourceNode->children[fieldNum];
-
-			size_t colonPos = currField->name.find ( ':' );
-			nsPrefix.assign ( currField->name.c_str(), colonPos );
-			bool nsOK = XMPMeta::GetNamespaceURI ( nsPrefix.c_str(), &nsURI, &nsLen );
-			if ( ! nsOK ) XMP_Throw ( "Source field namespace is not global", kXMPErr_BadSchema );
-			
-			XMP_Node * destSchema = FindSchemaNode ( &dest->tree, nsURI, kXMP_CreateNodes );
-			if ( destSchema == 0 ) XMP_Throw ( "Failed to find destination schema", kXMPErr_BadSchema );
-
-			XMP_Node * copyNode = new XMP_Node ( destSchema, currField->name, currField->value, currField->options );
-			destSchema->children.push_back ( copyNode );
-			CloneOffspring ( currField, copyNode );
-
-		}
-		
-	} else {
-
-		// Find the root nodes for the source and destination subtrees.
-		
-		ExpandXPath ( sourceNS, sourceRoot, &sourcePath );
-		ExpandXPath ( destNS, destRoot, &destPath );
-	
-		sourceNode = FindConstNode ( &source.tree, sourcePath );
-		if ( sourceNode == 0 ) XMP_Throw ( "Can't find source subtree", kXMPErr_BadXPath );
-		
-		destNode = FindNode ( &dest->tree, destPath, kXMP_ExistingOnly );	// Dest must not yet exist.
-		if ( destNode != 0 ) XMP_Throw ( "Destination subtree must not exist", kXMPErr_BadXPath );
-		
-		destNode = FindNode ( &dest->tree, destPath, kXMP_CreateNodes );	// Now create the dest.
-		if ( destNode == 0 ) XMP_Throw ( "Can't create destination root node", kXMPErr_BadXPath );
-		
-		// Make sure the destination is not within the source! The source can't be inside the destination
-		// because the source already existed and the destination was just created.
-		
-		if ( &source == dest ) {
-			for ( XMP_Node * testNode = destNode; testNode != 0; testNode = testNode->parent ) {
-				if ( testNode == sourceNode ) {
-					// *** delete the just-created dest root node
-					XMP_Throw ( "Destination subtree is within the source subtree", kXMPErr_BadXPath );
-				}
-			}
-		}
-	
-		// *** Could use a CloneTree util here and maybe elsewhere.
-		
-		destNode->value	  = sourceNode->value;	// *** Should use SetNode.
-		destNode->options = sourceNode->options;
-		CloneOffspring ( sourceNode, destNode );
-
-	}
-
-}	// DuplicateSubtree
-
-
-// =================================================================================================
diff --git a/xmpsdk/src/XMPUtils.cpp b/xmpsdk/src/XMPUtils.cpp
deleted file mode 100644
index dd0d2ceb..00000000
--- a/xmpsdk/src/XMPUtils.cpp
+++ /dev/null
@@ -1,2135 +0,0 @@
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:	Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"	// ! This must be the first include!
-#include "XMPCore_Impl.hpp"
-
-#include "XMPUtils.hpp"
-
-#include "MD5.h"
-
-#include <map>
-
-#include <time.h>
-#include <string.h>
-#include <stdlib.h>
-#include <locale.h>
-#include <errno.h>
-
-#include <stdio.h>	// For snprintf.
-
-#if XMP_WinBuild
-#ifdef _MSC_VER
-	#pragma warning ( disable : 4800 )	// forcing value to bool 'true' or 'false' (performance warning)
-	#pragma warning ( disable : 4996 )	// '...' was declared deprecated
-#endif
-#endif
-
-// =================================================================================================
-// Local Types and Constants
-// =========================
-
-static const char * sBase64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-// =================================================================================================
-// Static Variables
-// ================
-
-XMP_VarString * sComposedPath = 0;		// *** Only really need 1 string. Shrink periodically?
-XMP_VarString * sConvertedValue = 0;
-XMP_VarString * sBase64Str = 0;
-XMP_VarString * sCatenatedItems = 0;
-XMP_VarString * sStandardXMP = 0;
-XMP_VarString * sExtendedXMP = 0;
-XMP_VarString * sExtendedDigest = 0;
-
-// =================================================================================================
-// Local Utilities
-// ===============
-
-
-// -------------------------------------------------------------------------------------------------
-// ANSI Time Functions
-// -------------------
-//
-// A bit of hackery to use the best available time functions. Mac and UNIX have thread safe versions
-// of gmtime and localtime. On Mac the CodeWarrior functions are buggy, use Apple's.
-
-#if XMP_UNIXBuild
-
-	typedef time_t			ansi_tt;
-	typedef struct tm		ansi_tm;
-
-	#define ansi_time		time
-	#define ansi_mktime		mktime
-	#define ansi_difftime	difftime
-
-	#define ansi_gmtime		gmtime_r
-	#define ansi_localtime	localtime_r
-
-#elif XMP_WinBuild
-
-	// ! VS.Net 2003 (VC7) does not provide thread safe versions of gmtime and localtime.
-	// ! VS.Net 2005 (VC8) inverts the parameters for the safe versions of gmtime and localtime.
-
-	typedef time_t			ansi_tt;
-	typedef struct tm		ansi_tm;
-
-	#define ansi_time		time
-	#define ansi_mktime		mktime
-	#define ansi_difftime	difftime
-
-	#if defined(_MSC_VER) && (_MSC_VER >= 1400)
-		#define ansi_gmtime(tt,tm)		gmtime_s ( tm, tt )
-		#define ansi_localtime(tt,tm)	localtime_s ( tm, tt )
-	#else
-		static inline void ansi_gmtime ( const ansi_tt * ttTime, ansi_tm * tmTime )
-		{
-			ansi_tm * tmx = gmtime ( ttTime );	// ! Hope that there is no race!
-			if ( tmx == 0 ) XMP_Throw ( "Failure from ANSI C gmtime function", kXMPErr_ExternalFailure );
-			*tmTime = *tmx;
-		}
-		static inline void ansi_localtime ( const ansi_tt * ttTime, ansi_tm * tmTime )
-		{
-			ansi_tm * tmx = localtime ( ttTime );	// ! Hope that there is no race!
-			if ( tmx == 0 ) XMP_Throw ( "Failure from ANSI C localtime function", kXMPErr_ExternalFailure );
-			*tmTime = *tmx;
-		}
-	#endif
-
-#elif XMP_MacBuild
-
-	#if ! __MWERKS__
-
-		typedef time_t			ansi_tt;
-		typedef struct tm		ansi_tm;
-
-		#define ansi_time		time
-		#define ansi_mktime		mktime
-		#define ansi_difftime	difftime
-
-		#define ansi_gmtime		gmtime_r
-		#define ansi_localtime	localtime_r
-
-	#else
-
-		// ! The CW versions are buggy. Use Apple's code, time_t, and "struct tm".
-
-		#include <mach-o/dyld.h>
-
-		typedef _BSD_TIME_T_	ansi_tt;
-
-		typedef struct apple_tm {
-			int tm_sec;		/* seconds after the minute [0-60] */
-			int tm_min;		/* minutes after the hour [0-59] */
-			int tm_hour;	/* hours since midnight [0-23] */
-			int tm_mday;	/* day of the month [1-31] */
-			int tm_mon;		/* months since January [0-11] */
-			int tm_year;	/* years since 1900 */
-			int tm_wday;	/* days since Sunday [0-6] */
-			int tm_yday;	/* days since January 1 [0-365] */
-			int tm_isdst;	/* Daylight Savings Time flag */
-			long	tm_gmtoff;	/* offset from CUT in seconds */
-			char	*tm_zone;	/* timezone abbreviation */
-		} ansi_tm;
-
-
-		typedef ansi_tt (* GetTimeProc)	 ( ansi_tt * ttTime );
-		typedef ansi_tt (* MakeTimeProc) ( ansi_tm * tmTime );
-		typedef double	(* DiffTimeProc) ( ansi_tt t1, ansi_tt t0 );
-
-		typedef void (* ConvertTimeProc) ( const ansi_tt * ttTime, ansi_tm * tmTime );
-
-		static GetTimeProc ansi_time = 0;
-		static MakeTimeProc ansi_mktime = 0;
-		static DiffTimeProc ansi_difftime = 0;
-
-		static ConvertTimeProc ansi_gmtime = 0;
-		static ConvertTimeProc ansi_localtime = 0;
-
-		static void LookupTimeProcs()
-		{
-			_dyld_lookup_and_bind_with_hint ( "_time", "libSystem", (XMP_Uns32*)&ansi_time, 0 );
-			_dyld_lookup_and_bind_with_hint ( "_mktime", "libSystem", (XMP_Uns32*)&ansi_mktime, 0 );
-			_dyld_lookup_and_bind_with_hint ( "_difftime", "libSystem", (XMP_Uns32*)&ansi_difftime, 0 );
-			_dyld_lookup_and_bind_with_hint ( "_gmtime_r", "libSystem", (XMP_Uns32*)&ansi_gmtime, 0 );
-			_dyld_lookup_and_bind_with_hint ( "_localtime_r", "libSystem", (XMP_Uns32*)&ansi_localtime, 0 );
-		}
-
-	#endif
-
-#endif
-
-
-// -------------------------------------------------------------------------------------------------
-// IsLeapYear
-// ----------
-
-static bool
-IsLeapYear ( long year )
-{
-
-	if ( year < 0 ) year = -year + 1;		// Fold the negative years, assuming there is a year 0.
-
-	if ( (year % 4) != 0 ) return false;	// Not a multiple of 4.
-	if ( (year % 100) != 0 ) return true;	// A multiple of 4 but not a multiple of 100.
-	if ( (year % 400) == 0 ) return true;	// A multiple of 400.
-
-	return false;							// A multiple of 100 but not a multiple of 400.
-
-}	// IsLeapYear
-
-
-// -------------------------------------------------------------------------------------------------
-// DaysInMonth
-// -----------
-
-static int
-DaysInMonth ( XMP_Int32 year, XMP_Int32 month )
-{
-
-	static short	daysInMonth[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-									   // Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
-
-	int days = daysInMonth [ month ];
-	if ( (month == 2) && IsLeapYear ( year ) ) days += 1;
-
-	return days;
-
-}	// DaysInMonth
-
-
-// -------------------------------------------------------------------------------------------------
-// AdjustTimeOverflow
-// ------------------
-
-static void
-AdjustTimeOverflow ( XMP_DateTime * time )
-{
-	enum { kBillion = 1000*1000*1000L };
-
-	// ----------------------------------------------------------------------------------------------
-	// To be safe against pathalogical overflow we first adjust from month to second, then from
-	// nanosecond back up to month. This leaves each value closer to zero before propagating into it.
-	// For example if the hour and minute are both near max, adjusting minutes first can cause the
-	// hour to overflow.
-
-	// ! Photoshop 8 creates "time only" values with zeros for year, month, and day.
-
-	if ( (time->year != 0) || (time->month != 0) || (time->day != 0) ) {
-
-		while ( time->month < 1 ) {
-			time->year -= 1;
-			time->month += 12;
-		}
-
-		while ( time->month > 12 ) {
-			time->year += 1;
-			time->month -= 12;
-		}
-
-		while ( time->day < 1 ) {
-			time->month -= 1;
-			if ( time->month < 1 ) {	// ! Keep the months in range for indexing daysInMonth!
-				time->year -= 1;
-				time->month += 12;
-			}
-			time->day += DaysInMonth ( time->year, time->month );	// ! Decrement month before so index here is right!
-		}
-
-		while ( time->day > DaysInMonth ( time->year, time->month ) ) {
-			time->day -= DaysInMonth ( time->year, time->month );	// ! Increment month after so index here is right!
-			time->month += 1;
-			if ( time->month > 12 ) {
-				time->year += 1;
-				time->month -= 12;
-			}
-		}
-
-	}
-
-	while ( time->hour < 0 ) {
-		time->day -= 1;
-		time->hour += 24;
-	}
-
-	while ( time->hour >= 24 ) {
-		time->day += 1;
-		time->hour -= 24;
-	}
-
-	while ( time->minute < 0 ) {
-		time->hour -= 1;
-		time->minute += 60;
-	}
-
-	while ( time->minute >= 60 ) {
-		time->hour += 1;
-		time->minute -= 60;
-	}
-
-	while ( time->second < 0 ) {
-		time->minute -= 1;
-		time->second += 60;
-	}
-
-	while ( time->second >= 60 ) {
-		time->minute += 1;
-		time->second -= 60;
-	}
-
-	while ( time->nanoSecond < 0 ) {
-		time->second -= 1;
-		time->nanoSecond += kBillion;
-	}
-
-	while ( time->nanoSecond >= kBillion ) {
-		time->second += 1;
-		time->nanoSecond -= kBillion;
-	}
-
-	while ( time->second < 0 ) {
-		time->minute -= 1;
-		time->second += 60;
-	}
-
-	while ( time->second >= 60 ) {
-		time->minute += 1;
-		time->second -= 60;
-	}
-
-	while ( time->minute < 0 ) {
-		time->hour -= 1;
-		time->minute += 60;
-	}
-
-	while ( time->minute >= 60 ) {
-		time->hour += 1;
-		time->minute -= 60;
-	}
-
-	while ( time->hour < 0 ) {
-		time->day -= 1;
-		time->hour += 24;
-	}
-
-	while ( time->hour >= 24 ) {
-		time->day += 1;
-		time->hour -= 24;
-	}
-
-	if ( (time->year != 0) || (time->month != 0) || (time->day != 0) ) {
-
-		while ( time->month < 1 ) { // Make sure the months are OK first, for DaysInMonth.
-			time->year -= 1;
-			time->month += 12;
-		}
-
-		while ( time->month > 12 ) {
-			time->year += 1;
-			time->month -= 12;
-		}
-
-		while ( time->day < 1 ) {
-			time->month -= 1;
-			if ( time->month < 1 ) {
-				time->year -= 1;
-				time->month += 12;
-			}
-			time->day += DaysInMonth ( time->year, time->month );
-		}
-
-		while ( time->day > DaysInMonth ( time->year, time->month ) ) {
-			time->day -= DaysInMonth ( time->year, time->month );
-			time->month += 1;
-			if ( time->month > 12 ) {
-				time->year += 1;
-				time->month -= 12;
-			}
-		}
-
-	}
-
-}	// AdjustTimeOverflow
-
-
-// -------------------------------------------------------------------------------------------------
-// GatherInt
-// ---------
-
-static XMP_Int32
-GatherInt ( XMP_StringPtr strValue, size_t * _pos, const char * errMsg )
-{
-	size_t	 pos   = *_pos;
-	XMP_Int32 value = 0;
-
-	for ( char ch = strValue[pos]; ('0' <= ch) && (ch <= '9'); ++pos, ch = strValue[pos] ) {
-		value = (value * 10) + (ch - '0');
-	}
-
-	if ( pos == *_pos ) XMP_Throw ( errMsg, kXMPErr_BadParam );
-	*_pos = pos;
-	return value;
-
-}	// GatherInt
-
-
-// -------------------------------------------------------------------------------------------------
-
-static void FormatFullDateTime ( XMP_DateTime & tempDate, char * buffer, size_t bufferLen )
-{
-
-	AdjustTimeOverflow ( &tempDate );	// Make sure all time parts are in range.
-
-	if ( (tempDate.second == 0) && (tempDate.nanoSecond == 0) ) {
-
-		// Output YYYY-MM-DDThh:mmTZD.
-		snprintf ( buffer, bufferLen, "%.4d-%02d-%02dT%02d:%02d",	// AUDIT: Callers pass sizeof(buffer).
-                           static_cast<int>(tempDate.year), static_cast<int>(tempDate.month), static_cast<int>(tempDate.day), static_cast<int>(tempDate.hour), static_cast<int>(tempDate.minute) );
-
-	} else if ( tempDate.nanoSecond == 0  ) {
-
-		// Output YYYY-MM-DDThh:mm:ssTZD.
-		snprintf ( buffer, bufferLen, "%.4d-%02d-%02dT%02d:%02d:%02d",	// AUDIT: Callers pass sizeof(buffer).
-                           static_cast<int>(tempDate.year), static_cast<int>(tempDate.month), static_cast<int>(tempDate.day),
-                           static_cast<int>(tempDate.hour), static_cast<int>(tempDate.minute), static_cast<int>(tempDate.second) );
-
-	} else {
-
-		// Output YYYY-MM-DDThh:mm:ss.sTZD.
-		snprintf ( buffer, bufferLen, "%.4d-%02d-%02dT%02d:%02d:%02d.%09d", // AUDIT: Callers pass sizeof(buffer).
-                           static_cast<int>(tempDate.year), static_cast<int>(tempDate.month), static_cast<int>(tempDate.day),
-                           static_cast<int>(tempDate.hour), static_cast<int>(tempDate.minute), static_cast<int>(tempDate.second), static_cast<int>(tempDate.nanoSecond) );
-		for ( size_t i = strlen(buffer)-1; buffer[i] == '0'; --i ) buffer[i] = 0;	// Trim excess digits.
-
-	}
-
-}	// FormatFullDateTime
-
-
-// -------------------------------------------------------------------------------------------------
-// DecodeBase64Char
-// ----------------
-
-// The decode mapping:
-//
-//	encoded		encoded			raw
-//	char		value			value
-//	-------		-------			-----
-//	A .. Z		0x41 .. 0x5A	 0 .. 25
-//	a .. z		0x61 .. 0x7A	26 .. 51
-//	0 .. 9		0x30 .. 0x39	52 .. 61
-//	+			0x2B			62
-//	/			0x2F			63
-
-static unsigned char
-DecodeBase64Char ( XMP_Uns8 ch )
-{
-
-	if ( ('A' <= ch) && (ch <= 'Z') ) {
-		ch = ch - 'A';
-	} else if ( ('a' <= ch) && (ch <= 'z') ) {
-		ch = ch - 'a' + 26;
-	} else if ( ('0' <= ch) && (ch <= '9') ) {
-		ch = ch - '0' + 52;
-	} else if ( ch == '+' ) {
-		ch = 62;
-	} else if ( ch == '/' ) {
-		ch = 63;
-	} else if ( (ch == ' ') || (ch == kTab) || (ch == kLF) || (ch == kCR) ) {
-		ch = 0xFF;	// Will be ignored by the caller.
-	} else {
-		XMP_Throw ( "Invalid base-64 encoded character", kXMPErr_BadParam );
-	}
-
-	return ch;
-
-}	// DecodeBase64Char ();
-
-
-// -------------------------------------------------------------------------------------------------
-// EstimateSizeForJPEG
-// -------------------
-//
-// Estimate the serialized size for the subtree of an XMP_Node. Support for PackageForJPEG.
-
-static size_t
-EstimateSizeForJPEG ( const XMP_Node * xmpNode )
-{
-
-	size_t estSize = 0;
-	size_t nameSize = xmpNode->name.size();
-	bool   includeName = (! XMP_PropIsArray ( xmpNode->parent->options ));
-
-	if ( XMP_PropIsSimple ( xmpNode->options ) ) {
-
-		if ( includeName ) estSize += (nameSize + 3);	// Assume attribute form.
-		estSize += xmpNode->value.size();
-
-	} else if ( XMP_PropIsArray ( xmpNode->options ) ) {
-
-		// The form of the value portion is: <rdf:Xyz><rdf:li>...</rdf:li>...</rdf:Xyx>
-		if ( includeName ) estSize += (2*nameSize + 5);
-		size_t arraySize = xmpNode->children.size();
-		estSize += 9 + 10;	// The rdf:Xyz tags.
-		estSize += arraySize * (8 + 9);	// The rdf:li tags.
-		for ( size_t i = 0; i < arraySize; ++i ) {
-			estSize += EstimateSizeForJPEG ( xmpNode->children[i] );
-		}
-
-	} else {
-
-		// The form is: <headTag rdf:parseType="Resource">...fields...</tailTag>
-		if ( includeName ) estSize += (2*nameSize + 5);
-		estSize += 25;	// The rdf:parseType="Resource" attribute.
-		size_t fieldCount = xmpNode->children.size();
-		for ( size_t i = 0; i < fieldCount; ++i ) {
-			estSize += EstimateSizeForJPEG ( xmpNode->children[i] );
-		}
-
-	}
-
-	return estSize;
-
-}	// EstimateSizeForJPEG
-
-
-// -------------------------------------------------------------------------------------------------
-// MoveOneProperty
-// ---------------
-
-static bool MoveOneProperty ( XMPMeta & stdXMP, XMPMeta * extXMP,
-							  XMP_StringPtr schemaURI, XMP_StringPtr propName )
-{
-
-	XMP_Node * propNode = 0;
-	XMP_NodePtrPos stdPropPos;
-
-	XMP_Node * stdSchema = FindSchemaNode ( &stdXMP.tree, schemaURI, kXMP_ExistingOnly, 0 );
-	if ( stdSchema != 0 ) {
-		propNode = FindChildNode ( stdSchema, propName, kXMP_ExistingOnly, &stdPropPos );
-	}
-	if ( propNode == 0 ) return false;
-
-	XMP_Node * extSchema = FindSchemaNode ( &extXMP->tree, schemaURI, kXMP_CreateNodes );
-
-	propNode->parent = extSchema;
-
-	extSchema->options &= ~kXMP_NewImplicitNode;
-	extSchema->children.push_back ( propNode );
-
-	stdSchema->children.erase ( stdPropPos );
-	DeleteEmptySchema ( stdSchema );
-
-	return true;
-
-}	// MoveOneProperty
-
-
-// -------------------------------------------------------------------------------------------------
-// CreateEstimatedSizeMap
-// ----------------------
-
-#ifndef Trace_PackageForJPEG
-	#define Trace_PackageForJPEG 0
-#endif
-
-typedef std::pair < XMP_VarString*, XMP_VarString* > StringPtrPair;
-typedef std::multimap < size_t, StringPtrPair > PropSizeMap;
-
-static void CreateEstimatedSizeMap ( XMPMeta & stdXMP, PropSizeMap * propSizes )
-{
-	#if Trace_PackageForJPEG
-		printf ( "  Creating top level property map:\n" );
-	#endif
-
-	for ( size_t s = stdXMP.tree.children.size(); s > 0; --s ) {
-
-		XMP_Node * stdSchema = stdXMP.tree.children[s-1];
-
-		for ( size_t p = stdSchema->children.size(); p > 0; --p ) {
-
-			XMP_Node * stdProp = stdSchema->children[p-1];
-			if ( (stdSchema->name == kXMP_NS_XMP_Note) &&
-				 (stdProp->name == "xmpNote:HasExtendedXMP") ) continue;	// ! Don't move xmpNote:HasExtendedXMP.
-
-			size_t propSize = EstimateSizeForJPEG ( stdProp );
-			StringPtrPair namePair ( &stdSchema->name, &stdProp->name );
-			PropSizeMap::value_type mapValue ( propSize, namePair );
-
-			(void) propSizes->insert ( propSizes->upper_bound ( propSize ), mapValue );
-			#if Trace_PackageForJPEG
-				printf ( "    %d bytes, %s in %s\n", propSize, stdProp->name.c_str(), stdSchema->name.c_str() );
-			#endif
-
-		}
-
-	}
-
-}	// CreateEstimatedSizeMap
-
-
-// -------------------------------------------------------------------------------------------------
-// MoveLargestProperty
-// -------------------
-
-static size_t MoveLargestProperty ( XMPMeta & stdXMP, XMPMeta * extXMP, PropSizeMap & propSizes )
-{
-	XMP_Assert ( ! propSizes.empty() );
-
-	#if 0
-		// *** Xcode 2.3 on Mac OS X 10.4.7 seems to have a bug where this does not pick the last
-		// *** item in the map. We'll just avoid it on all platforms until thoroughly tested.
-		PropSizeMap::iterator lastPos = propSizes.end();
-		--lastPos;	// Move to the actual last item.
-	#else
-		PropSizeMap::iterator lastPos = propSizes.begin();
-		PropSizeMap::iterator nextPos = lastPos;
-		for ( ++nextPos; nextPos != propSizes.end(); ++nextPos ) lastPos = nextPos;
-	#endif
-
-	size_t propSize = lastPos->first;
-	const char * schemaURI = lastPos->second.first->c_str();
-	const char * propName  = lastPos->second.second->c_str();
-
-	#if Trace_PackageForJPEG
-		printf ( "  Move %s, %d bytes\n", propName, propSize );
-	#endif
-
-    bool moved = MoveOneProperty ( stdXMP, extXMP, schemaURI, propName );
-	XMP_Assert ( moved );
-	UNUSED(moved);
-
-	propSizes.erase ( lastPos );
-	return propSize;
-
-}	// MoveLargestProperty
-
-
-// =================================================================================================
-// Class Static Functions
-// ======================
-
-
-// -------------------------------------------------------------------------------------------------
-// Initialize
-// ----------
-
-/* class static */ bool
-XMPUtils::Initialize()
-{
-	sComposedPath	= new XMP_VarString();
-	sConvertedValue = new XMP_VarString();
-	sBase64Str		= new XMP_VarString();
-	sCatenatedItems = new XMP_VarString();
-	sStandardXMP    = new XMP_VarString();
-	sExtendedXMP    = new XMP_VarString();
-	sExtendedDigest = new XMP_VarString();
-
-	#if XMP_MacBuild && __MWERKS__
-		LookupTimeProcs();
-	#endif
-
-	return true;
-
-}	// Initialize
-
-
-// -------------------------------------------------------------------------------------------------
-// Terminate
-// ---------
-
-#define EliminateGlobal(g) delete ( g ); g = 0
-
-/* class static */ void
-XMPUtils::Terminate() RELEASE_NO_THROW
-{
-	EliminateGlobal ( sComposedPath );
-	EliminateGlobal ( sConvertedValue );
-	EliminateGlobal ( sBase64Str );
-	EliminateGlobal ( sCatenatedItems );
-	EliminateGlobal ( sStandardXMP );
-	EliminateGlobal ( sExtendedXMP );
-	EliminateGlobal ( sExtendedDigest );
-
-	return;
-
-}	// Terminate
-
-
-// -------------------------------------------------------------------------------------------------
-// Unlock
-// ------
-
-/* class static */ void
-XMPUtils::Unlock ( XMP_OptionBits options )
-{
-	UNUSED(options);
-
-	XMPMeta::Unlock ( 0 );
-
-}	// Unlock
-
-// -------------------------------------------------------------------------------------------------
-// ComposeArrayItemPath
-// --------------------
-//
-// Return "arrayName[index]".
-
-/* class static */ void
-XMPUtils::ComposeArrayItemPath ( XMP_StringPtr	 schemaNS,
-								 XMP_StringPtr	 arrayName,
-								 XMP_Index		 itemIndex,
-								 XMP_StringPtr * fullPath,
-								 XMP_StringLen * pathSize )
-{
-	XMP_Assert ( schemaNS != 0 );	// Enforced by wrapper.
-	XMP_Assert ( *arrayName != 0 ); // Enforced by wrapper.
-	XMP_Assert ( (fullPath != 0) && (pathSize != 0) );	// Enforced by wrapper.
-
-	XMP_ExpandedXPath expPath;	// Just for side effects to check namespace and basic path.
-	ExpandXPath ( schemaNS, arrayName, &expPath );
-
-	if ( (itemIndex < 0) && (itemIndex != kXMP_ArrayLastItem) ) XMP_Throw ( "Array index out of bounds", kXMPErr_BadParam );
-
-	XMP_StringLen reserveLen = strlen(arrayName) + 2 + 32;	// Room plus padding.
-
-	sComposedPath->erase();
-	sComposedPath->reserve ( reserveLen );
-	sComposedPath->append ( reserveLen, ' ' );
-
-	if ( itemIndex != kXMP_ArrayLastItem ) {
-		// AUDIT: Using string->size() for the snprintf length is safe.
-                snprintf ( const_cast<char*>(sComposedPath->c_str()), sComposedPath->size(), "%s[%d]", arrayName, static_cast<int>(itemIndex) );
-	} else {
-		*sComposedPath = arrayName;
-		*sComposedPath += "[last()] ";
-		(*sComposedPath)[sComposedPath->size()-1] = 0;	// ! Final null is for the strlen at exit.
-	}
-
-	*fullPath = sComposedPath->c_str();
-	*pathSize = strlen ( *fullPath );	// ! Don't use sComposedPath->size()!
-
-	XMP_Enforce ( *pathSize < sComposedPath->size() );	// Rather late, but complain about buffer overflow.
-
-}	// ComposeArrayItemPath
-
-
-// -------------------------------------------------------------------------------------------------
-// ComposeStructFieldPath
-// ----------------------
-//
-// Return "structName/ns:fieldName".
-
-/* class static */ void
-XMPUtils::ComposeStructFieldPath ( XMP_StringPtr   schemaNS,
-								   XMP_StringPtr   structName,
-								   XMP_StringPtr   fieldNS,
-								   XMP_StringPtr   fieldName,
-								   XMP_StringPtr * fullPath,
-								   XMP_StringLen * pathSize )
-{
-	XMP_Assert ( (schemaNS != 0) && (fieldNS != 0) );		// Enforced by wrapper.
-	XMP_Assert ( (*structName != 0) && (*fieldName != 0) ); // Enforced by wrapper.
-	XMP_Assert ( (fullPath != 0) && (pathSize != 0) );		// Enforced by wrapper.
-
-	XMP_ExpandedXPath expPath;	// Just for side effects to check namespace and basic path.
-	ExpandXPath ( schemaNS, structName, &expPath );
-
-	XMP_ExpandedXPath fieldPath;
-	ExpandXPath ( fieldNS, fieldName, &fieldPath );
-	if ( fieldPath.size() != 2 ) XMP_Throw ( "The fieldName must be simple", kXMPErr_BadXPath );
-
-	XMP_StringLen reserveLen = strlen(structName) + fieldPath[kRootPropStep].step.size() + 1;
-
-	sComposedPath->erase();
-	sComposedPath->reserve ( reserveLen );
-	*sComposedPath = structName;
-	*sComposedPath += '/';
-	*sComposedPath += fieldPath[kRootPropStep].step;
-
-	*fullPath = sComposedPath->c_str();
-	*pathSize = sComposedPath->size();
-
-}	// ComposeStructFieldPath
-
-
-// -------------------------------------------------------------------------------------------------
-// ComposeQualifierPath
-// --------------------
-//
-// Return "propName/?ns:qualName".
-
-/* class static */ void
-XMPUtils::ComposeQualifierPath ( XMP_StringPtr	 schemaNS,
-								 XMP_StringPtr	 propName,
-								 XMP_StringPtr	 qualNS,
-								 XMP_StringPtr	 qualName,
-								 XMP_StringPtr * fullPath,
-								 XMP_StringLen * pathSize )
-{
-	XMP_Assert ( (schemaNS != 0) && (qualNS != 0) );		// Enforced by wrapper.
-	XMP_Assert ( (*propName != 0) && (*qualName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (fullPath != 0) && (pathSize != 0) );		// Enforced by wrapper.
-
-	XMP_ExpandedXPath expPath;	// Just for side effects to check namespace and basic path.
-	ExpandXPath ( schemaNS, propName, &expPath );
-
-	XMP_ExpandedXPath qualPath;
-	ExpandXPath ( qualNS, qualName, &qualPath );
-	if ( qualPath.size() != 2 ) XMP_Throw ( "The qualifier name must be simple", kXMPErr_BadXPath );
-
-	XMP_StringLen reserveLen = strlen(propName) + qualPath[kRootPropStep].step.size() + 2;
-
-	sComposedPath->erase();
-	sComposedPath->reserve ( reserveLen );
-	*sComposedPath = propName;
-	*sComposedPath += "/?";
-	*sComposedPath += qualPath[kRootPropStep].step;
-
-	*fullPath = sComposedPath->c_str();
-	*pathSize = sComposedPath->size();
-
-}	// ComposeQualifierPath
-
-
-// -------------------------------------------------------------------------------------------------
-// ComposeLangSelector
-// -------------------
-//
-// Return "arrayName[?xml:lang="lang"]".
-
-// *** #error "handle quotes in the lang - or verify format"
-
-/* class static */ void
-XMPUtils::ComposeLangSelector ( XMP_StringPtr	schemaNS,
-								XMP_StringPtr	arrayName,
-								XMP_StringPtr	_langName,
-								XMP_StringPtr * fullPath,
-								XMP_StringLen * pathSize )
-{
-	XMP_Assert ( schemaNS != 0 );	// Enforced by wrapper.
-	XMP_Assert ( (*arrayName != 0) && (*_langName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (fullPath != 0) && (pathSize != 0) );		// Enforced by wrapper.
-
-	XMP_ExpandedXPath expPath;	// Just for side effects to check namespace and basic path.
-	ExpandXPath ( schemaNS, arrayName, &expPath );
-
-	XMP_VarString langName ( _langName );
-	NormalizeLangValue ( &langName );
-
-	XMP_StringLen reserveLen = strlen(arrayName) + langName.size() + 14;
-
-	sComposedPath->erase();
-	sComposedPath->reserve ( reserveLen );
-	*sComposedPath = arrayName;
-	*sComposedPath += "[?xml:lang=\"";
-	*sComposedPath += langName;
-	*sComposedPath += "\"]";
-
-	*fullPath = sComposedPath->c_str();
-	*pathSize = sComposedPath->size();
-
-}	// ComposeLangSelector
-
-
-// -------------------------------------------------------------------------------------------------
-// ComposeFieldSelector
-// --------------------
-//
-// Return "arrayName[ns:fieldName="fieldValue"]".
-
-// *** #error "handle quotes in the value"
-
-/* class static */ void
-XMPUtils::ComposeFieldSelector ( XMP_StringPtr	 schemaNS,
-								 XMP_StringPtr	 arrayName,
-								 XMP_StringPtr	 fieldNS,
-								 XMP_StringPtr	 fieldName,
-								 XMP_StringPtr	 fieldValue,
-								 XMP_StringPtr * fullPath,
-								 XMP_StringLen * pathSize )
-{
-	XMP_Assert ( (schemaNS != 0) && (fieldNS != 0) && (fieldValue != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (*arrayName != 0) && (*fieldName != 0) );	// Enforced by wrapper.
-	XMP_Assert ( (fullPath != 0) && (pathSize != 0) );		// Enforced by wrapper.
-
-	XMP_ExpandedXPath expPath;	// Just for side effects to check namespace and basic path.
-	ExpandXPath ( schemaNS, arrayName, &expPath );
-
-	XMP_ExpandedXPath fieldPath;
-	ExpandXPath ( fieldNS, fieldName, &fieldPath );
-	if ( fieldPath.size() != 2 ) XMP_Throw ( "The fieldName must be simple", kXMPErr_BadXPath );
-
-	XMP_StringLen reserveLen = strlen(arrayName) + fieldPath[kRootPropStep].step.size() + strlen(fieldValue) + 5;
-
-	sComposedPath->erase();
-	sComposedPath->reserve ( reserveLen );
-	*sComposedPath = arrayName;
-	*sComposedPath += '[';
-	*sComposedPath += fieldPath[kRootPropStep].step;
-	*sComposedPath += "=\"";
-	*sComposedPath += fieldValue;
-	*sComposedPath += "\"]";
-
-	*fullPath = sComposedPath->c_str();
-	*pathSize = sComposedPath->size();
-
-}	// ComposeFieldSelector
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertFromBool
-// ---------------
-
-/* class static */ void
-XMPUtils::ConvertFromBool ( bool			binValue,
-							XMP_StringPtr * strValue,
-							XMP_StringLen * strSize )
-{
-	XMP_Assert ( (strValue != 0) && (strSize != 0) );	// Enforced by wrapper.
-
-	if ( binValue ) {
-		*strValue = kXMP_TrueStr;
-		*strSize  = strlen ( kXMP_TrueStr );
-	} else {
-		*strValue = kXMP_FalseStr;
-		*strSize  = strlen ( kXMP_FalseStr );
-	}
-
-}	// ConvertFromBool
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertFromInt
-// --------------
-
-/* class static */ void
-XMPUtils::ConvertFromInt ( XMP_Int32	   binValue,
-						   XMP_StringPtr   format,
-						   XMP_StringPtr * strValue,
-						   XMP_StringLen * strSize )
-{
-	XMP_Assert ( (format != 0) && (strValue != 0) && (strSize != 0) );	// Enforced by wrapper.
-
-	if ( *format == 0 ) format = "%d";
-
-	sConvertedValue->erase();
-	sConvertedValue->reserve ( 100 );		// More than enough for any reasonable format and value.
-	sConvertedValue->append ( 100, ' ' );
-
-	// AUDIT: Using string->size() for the snprintf length is safe.
-	snprintf ( const_cast<char*>(sConvertedValue->c_str()), sConvertedValue->size(), format, binValue );
-
-	*strValue = sConvertedValue->c_str();
-	*strSize  = strlen ( *strValue );	// ! Don't use sConvertedValue->size()!
-
-	XMP_Enforce ( *strSize < sConvertedValue->size() ); // Rather late, but complain about buffer overflow.
-
-}	// ConvertFromInt
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertFromInt64
-// ----------------
-
-/* class static */ void
-XMPUtils::ConvertFromInt64 ( XMP_Int64	     binValue,
-						     XMP_StringPtr   format,
-						     XMP_StringPtr * strValue,
-						     XMP_StringLen * strSize )
-{
-	XMP_Assert ( (format != 0) && (strValue != 0) && (strSize != 0) );	// Enforced by wrapper.
-
-	if ( *format == 0 ) format = "%lld";
-
-	sConvertedValue->erase();
-	sConvertedValue->reserve ( 100 );		// More than enough for any reasonable format and value.
-	sConvertedValue->append ( 100, ' ' );
-
-	// AUDIT: Using string->size() for the snprintf length is safe.
-	snprintf ( const_cast<char*>(sConvertedValue->c_str()), sConvertedValue->size(), format, binValue );
-
-	*strValue = sConvertedValue->c_str();
-	*strSize  = strlen ( *strValue );	// ! Don't use sConvertedValue->size()!
-
-	XMP_Enforce ( *strSize < sConvertedValue->size() ); // Rather late, but complain about buffer overflow.
-
-}	// ConvertFromInt64
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertFromFloat
-// ----------------
-
-/* class static */ void
-XMPUtils::ConvertFromFloat ( double			 binValue,
-							 XMP_StringPtr	 format,
-							 XMP_StringPtr * strValue,
-							 XMP_StringLen * strSize )
-{
-	XMP_Assert ( (format != 0) && (strValue != 0) && (strSize != 0) );	// Enforced by wrapper.
-
-	if ( *format == 0 ) format = "%f";
-
-	sConvertedValue->erase();
-	sConvertedValue->reserve ( 1000 );		// More than enough for any reasonable format and value.
-	sConvertedValue->append ( 1000, ' ' );
-
-	// AUDIT: Using string->size() for the snprintf length is safe.
-	snprintf ( const_cast<char*>(sConvertedValue->c_str()), sConvertedValue->size(), format, binValue );
-
-	*strValue = sConvertedValue->c_str();
-	*strSize  = strlen ( *strValue );	// ! Don't use sConvertedValue->size()!
-
-	XMP_Enforce ( *strSize < sConvertedValue->size() ); // Rather late, but complain about buffer overflow.
-
-}	// ConvertFromFloat
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertFromDate
-// ---------------
-//
-// Format a date according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime:
-//	YYYY
-//	YYYY-MM
-//	YYYY-MM-DD
-//	YYYY-MM-DDThh:mmTZD
-//	YYYY-MM-DDThh:mm:ssTZD
-//	YYYY-MM-DDThh:mm:ss.sTZD
-//
-//	YYYY = four-digit year
-//	MM	 = two-digit month (01=January, etc.)
-//	DD	 = two-digit day of month (01 through 31)
-//	hh	 = two digits of hour (00 through 23)
-//	mm	 = two digits of minute (00 through 59)
-//	ss	 = two digits of second (00 through 59)
-//	s	 = one or more digits representing a decimal fraction of a second
-//	TZD	 = time zone designator (Z or +hh:mm or -hh:mm)
-//
-// Note that ISO 8601 does not seem to allow years less than 1000 or greater than 9999. We allow
-// any year, even negative ones. The year is formatted as "%.4d".
-
-// *** Need to check backward compatibility for partial forms!
-
-/* class static */ void
-XMPUtils::ConvertFromDate ( const XMP_DateTime & binValue,
-							XMP_StringPtr *		 strValue,
-							XMP_StringLen *		 strSize )
-{
-	XMP_Assert ( (strValue != 0) && (strSize != 0) );	// Enforced by wrapper.
-
-	bool addTimeZone = false;
-	char buffer [100];	// Plenty long enough.
-
-	// Pick the format, use snprintf to format into a local buffer, assign to static output string.
-	// Don't use AdjustTimeOverflow at the start, that will wipe out zero month or day values.
-
-	// ! Photoshop 8 creates "time only" values with zeros for year, month, and day.
-
-	XMP_DateTime tempDate = binValue;
-
-	// Temporary fix for bug 1269463, silently fix out of range month or day.
-
-	bool haveDay  = (tempDate.day != 0);
-	bool haveTime = ( (tempDate.hour != 0)   || (tempDate.minute != 0) ||
-			          (tempDate.second != 0) || (tempDate.nanoSecond != 0) ||
-			          (tempDate.tzSign != 0) || (tempDate.tzHour != 0) || (tempDate.tzMinute != 0) );
-
-	if ( tempDate.month == 0 ) {
-		if ( haveDay || haveTime ) tempDate.month = 1;
-	} else {
-		if ( tempDate.month < 1 ) tempDate.month = 1;
-		if ( tempDate.month > 12 ) tempDate.month = 12;
-	}
-
-	if ( tempDate.day == 0 ) {
-		if ( haveTime ) tempDate.day = 1;
-	} else {
-		if ( tempDate.day < 1 ) tempDate.day = 1;
-		if ( tempDate.day > 31 ) tempDate.day = 31;
-	}
-
-	// Now carry on with the original logic.
-
-	if ( tempDate.month == 0 ) {
-
-		// Output YYYY if all else is zero, otherwise output a full string for the quasi-bogus
-		// "time only" values from Photoshop CS.
-		if ( (tempDate.day == 0) && (tempDate.hour == 0) && (tempDate.minute == 0) &&
-			 (tempDate.second == 0) && (tempDate.nanoSecond == 0) &&
-			 (tempDate.tzSign == 0) && (tempDate.tzHour == 0) && (tempDate.tzMinute == 0) ) {
-                    snprintf ( buffer, sizeof(buffer), "%.4d", static_cast<int>(tempDate.year) ); // AUDIT: Using sizeof for snprintf length is safe.
-		} else if ( (tempDate.year == 0) && (tempDate.day == 0) ) {
-			FormatFullDateTime ( tempDate, buffer, sizeof(buffer) );
-			addTimeZone = true;
-		} else {
-			XMP_Throw ( "Invalid partial date", kXMPErr_BadParam);
-		}
-
-	} else if ( tempDate.day == 0 ) {
-
-		// Output YYYY-MM.
-		if ( (tempDate.month < 1) || (tempDate.month > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam);
-		if ( (tempDate.hour != 0) || (tempDate.minute != 0) ||
-			 (tempDate.second != 0) || (tempDate.nanoSecond != 0) ||
-			 (tempDate.tzSign != 0) || (tempDate.tzHour != 0) || (tempDate.tzMinute != 0) ) {
-			XMP_Throw ( "Invalid partial date, non-zeros after zero month and day", kXMPErr_BadParam);
-		}
-		snprintf ( buffer, sizeof(buffer), "%.4d-%02d", static_cast<int>(tempDate.year), static_cast<int>(tempDate.month) );	// AUDIT: Using sizeof for snprintf length is safe.
-
-	} else if ( (tempDate.hour == 0) && (tempDate.minute == 0) &&
-				(tempDate.second == 0) && (tempDate.nanoSecond == 0) &&
-				(tempDate.tzSign == 0) && (tempDate.tzHour == 0) && (tempDate.tzMinute == 0) ) {
-
-		// Output YYYY-MM-DD.
-		if ( (tempDate.month < 1) || (tempDate.month > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam);
-		if ( (tempDate.day < 1) || (tempDate.day > 31) ) XMP_Throw ( "Day is out of range", kXMPErr_BadParam);
-		snprintf ( buffer, sizeof(buffer), "%.4d-%02d-%02d", static_cast<int>(tempDate.year), static_cast<int>(tempDate.month), static_cast<int>(tempDate.day) ); // AUDIT: Using sizeof for snprintf length is safe.
-
-	} else {
-
-		FormatFullDateTime ( tempDate, buffer, sizeof(buffer) );
-		addTimeZone = true;
-
-	}
-
-	sConvertedValue->assign ( buffer );
-
-	if ( addTimeZone ) {
-
-		if ( (tempDate.tzHour < 0) || (tempDate.tzHour > 23) ||
-			 (tempDate.tzMinute < 0 ) || (tempDate.tzMinute > 59) ||
-			 (tempDate.tzSign < -1) || (tempDate.tzSign > +1) ||
-			 ((tempDate.tzSign != 0) && (tempDate.tzHour == 0) && (tempDate.tzMinute == 0)) ||
-			 ((tempDate.tzSign == 0) && ((tempDate.tzHour != 0) || (tempDate.tzMinute != 0))) ) {
-			XMP_Throw ( "Invalid time zone values", kXMPErr_BadParam );
-		}
-
-		if ( tempDate.tzSign == 0 ) {
-			*sConvertedValue += 'Z';
-		} else {
-                    snprintf ( buffer, sizeof(buffer), "+%02d:%02d", static_cast<int>(tempDate.tzHour), static_cast<int>(tempDate.tzMinute) );	// AUDIT: Using sizeof for snprintf length is safe.
-			if ( tempDate.tzSign < 0 ) buffer[0] = '-';
-			*sConvertedValue += buffer;
-		}
-
-	}
-
-	*strValue = sConvertedValue->c_str();
-	*strSize  = sConvertedValue->size();
-
-}	// ConvertFromDate
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertToBool
-// -------------
-//
-// Formally the string value should be "True" or "False", but we should be more flexible here. Map
-// the string to lower case. Allow any of "true", "false", "t", "f", "1", or "0".
-
-/* class static */ bool
-XMPUtils::ConvertToBool ( XMP_StringPtr strValue )
-{
-	if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue );
-
-	bool result = false;
-	XMP_VarString strObj ( strValue );
-
-	for ( XMP_VarStringPos ch = strObj.begin(); ch != strObj.end(); ++ch ) {
-		if ( ('A' <= *ch) && (*ch <= 'Z') ) *ch += 0x20;
-	}
-
-	if ( (strObj == "true") || (strObj == "t") || (strObj == "1") ) {
-		result = true;
-	} else if ( (strObj == "false") || (strObj == "f") || (strObj == "0") ) {
-		result = false;
-	} else {
-		XMP_Throw ( "Invalid Boolean string", kXMPErr_BadParam );
-	}
-
-	return result;
-
-}	// ConvertToBool
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertToInt
-// ------------
-
-/* class static */ XMP_Int32
-XMPUtils::ConvertToInt ( XMP_StringPtr strValue )
-{
-	if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue );
-
-	int count;
-	char nextCh;
-	XMP_Int32 result;
-
-	if ( ! XMP_LitNMatch ( strValue, "0x", 2 ) ) {
-            count = sscanf ( strValue, "%d%c", (int*)&result, &nextCh );
-	} else {
-            count = sscanf ( strValue, "%x%c", (unsigned int*)&result, &nextCh );
-	}
-
-	if ( count != 1 ) XMP_Throw ( "Invalid integer string", kXMPErr_BadParam );
-
-	return result;
-
-}	// ConvertToInt
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertToInt64
-// --------------
-
-/* class static */ XMP_Int64
-XMPUtils::ConvertToInt64 ( XMP_StringPtr strValue )
-{
-#if defined(__MINGW32__)// || defined(__MINGW64__)
-    return ConvertToInt(strValue);
-#else
-	if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue );
-
-	int count;
-	char nextCh;
-	XMP_Int64 result;
-
-	if ( ! XMP_LitNMatch ( strValue, "0x", 2 ) ) {
-		count = sscanf ( strValue, "%lld%c", &result, &nextCh );
-	} else {
-		count = sscanf ( strValue, "%llx%c", &result, &nextCh );
-	}
-
-	if ( count != 1 ) XMP_Throw ( "Invalid integer string", kXMPErr_BadParam );
-
-	return result;
-#endif
-}	// ConvertToInt64
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertToFloat
-// --------------
-
-/* class static */ double
-XMPUtils::ConvertToFloat ( XMP_StringPtr strValue )
-{
-	if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue );
-
-	XMP_VarString oldLocale;	// Try to make sure number conversion uses '.' as the decimal point.
-	XMP_StringPtr oldLocalePtr = setlocale ( LC_ALL, 0 );
-	if ( oldLocalePtr != 0 ) {
-		oldLocale.assign ( oldLocalePtr );
-		setlocale ( LC_ALL, "C" );
-	}
-
-	errno = 0;
-	char * numEnd;
-	double result = strtod ( strValue, &numEnd );
-
-	if ( oldLocalePtr != 0 ) setlocale ( LC_ALL, oldLocalePtr );	// ! Reset locale before possible throw!
-	if ( (errno != 0) || (*numEnd != 0) ) XMP_Throw ( "Invalid float string", kXMPErr_BadParam );
-
-	return result;
-
-}	// ConvertToFloat
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertToDate
-// -------------
-//
-// Parse a date according to ISO 8601 and http://www.w3.org/TR/NOTE-datetime:
-//	YYYY
-//	YYYY-MM
-//	YYYY-MM-DD
-//	YYYY-MM-DDThh:mmTZD
-//	YYYY-MM-DDThh:mm:ssTZD
-//	YYYY-MM-DDThh:mm:ss.sTZD
-//
-//	YYYY = four-digit year
-//	MM	 = two-digit month (01=January, etc.)
-//	DD	 = two-digit day of month (01 through 31)
-//	hh	 = two digits of hour (00 through 23)
-//	mm	 = two digits of minute (00 through 59)
-//	ss	 = two digits of second (00 through 59)
-//	s	 = one or more digits representing a decimal fraction of a second
-//	TZD	 = time zone designator (Z or +hh:mm or -hh:mm)
-//
-// Note that ISO 8601 does not seem to allow years less than 1000 or greater than 9999. We allow
-// any year, even negative ones. The year is formatted as "%.4d".
-
-// ! Tolerate missing TZD, assume the time is in local time
-// ! Tolerate missing date portion, in case someone foolishly writes a time-only value that way.
-
-// *** Put the ISO format comments in the header documentation.
-
-/* class static */ void
-XMPUtils::ConvertToDate ( XMP_StringPtr	 strValue,
-						  XMP_DateTime * binValue )
-{
-	if ( (strValue == 0) || (*strValue == 0) ) XMP_Throw ( "Empty convert-from string", kXMPErr_BadValue);
-
-	size_t	 pos = 0;
-	XMP_Int32 temp;
-
-	XMP_Assert ( sizeof(*binValue) == sizeof(XMP_DateTime) );
-	(void) memset ( binValue, 0, sizeof(*binValue) );	// AUDIT: Safe, using sizeof destination.
-
-	bool timeOnly = ( (strValue[0] == 'T') ||
-					  ((strlen(strValue) >= 2) && (strValue[1] == ':')) ||
-					  ((strlen(strValue) >= 3) && (strValue[2] == ':')) );
-
-	if ( ! timeOnly ) {
-
-		if ( strValue[0] == '-' ) pos = 1;
-
-		temp = GatherInt ( strValue, &pos, "Invalid year in date string" ); // Extract the year.
-		if ( (strValue[pos] != 0) && (strValue[pos] != '-') ) XMP_Throw ( "Invalid date string, after year", kXMPErr_BadParam );
-		if ( strValue[0] == '-' ) temp = -temp;
-		binValue->year = temp;
-		if ( strValue[pos] == 0 ) return;
-
-		++pos;
-		temp = GatherInt ( strValue, &pos, "Invalid month in date string" );	// Extract the month.
-		if ( (strValue[pos] != 0) && (strValue[pos] != '-') ) XMP_Throw ( "Invalid date string, after month", kXMPErr_BadParam );
-		binValue->month = temp;
-		if ( strValue[pos] == 0 ) return;
-
-		++pos;
-		temp = GatherInt ( strValue, &pos, "Invalid day in date string" );	// Extract the day.
-		if ( (strValue[pos] != 0) && (strValue[pos] != 'T') ) XMP_Throw ( "Invalid date string, after day", kXMPErr_BadParam );
-		binValue->day = temp;
-		if ( strValue[pos] == 0 ) return;
-
-		// Allow year, month, and day to all be zero; implies the date portion is missing.
-		if ( (binValue->year != 0) || (binValue->month != 0) || (binValue->day != 0) ) {
-			// Temporary fix for bug 1269463, silently fix out of range month or day.
-			// if ( (binValue->month < 1) || (binValue->month > 12) ) XMP_Throw ( "Month is out of range", kXMPErr_BadParam );
-			// if ( (binValue->day < 1) || (binValue->day > 31) ) XMP_Throw ( "Day is out of range", kXMPErr_BadParam );
-			if ( binValue->month < 1 ) binValue->month = 1;
-			if ( binValue->month > 12 ) binValue->month = 12;
-			if ( binValue->day < 1 ) binValue->day = 1;
-			if ( binValue->day > 31 ) binValue->day = 31;
-		}
-
-	}
-
-	if ( strValue[pos] == 'T' ) {
-		++pos;
-	} else if ( ! timeOnly ) {
-		XMP_Throw ( "Invalid date string, missing 'T' after date", kXMPErr_BadParam );
-	}
-
-	temp = GatherInt ( strValue, &pos, "Invalid hour in date string" ); // Extract the hour.
-	if ( strValue[pos] != ':' ) XMP_Throw ( "Invalid date string, after hour", kXMPErr_BadParam );
-	if ( temp > 23 ) temp = 23;	// *** 1269463: XMP_Throw ( "Hour is out of range", kXMPErr_BadParam );
-	binValue->hour = temp;
-	// Don't check for done, we have to work up to the time zone.
-
-	++pos;
-	temp = GatherInt ( strValue, &pos, "Invalid minute in date string" );	// And the minute.
-	if ( (strValue[pos] != ':') && (strValue[pos] != 'Z') &&
-		 (strValue[pos] != '+') && (strValue[pos] != '-') && (strValue[pos] != 0) ) XMP_Throw ( "Invalid date string, after minute", kXMPErr_BadParam );
-	if ( temp > 59 ) temp = 59;	// *** 1269463: XMP_Throw ( "Minute is out of range", kXMPErr_BadParam );
-	binValue->minute = temp;
-	// Don't check for done, we have to work up to the time zone.
-
-	if ( strValue[pos] == ':' ) {
-
-		++pos;
-		temp = GatherInt ( strValue, &pos, "Invalid whole seconds in date string" );	// Extract the whole seconds.
-		if ( (strValue[pos] != '.') && (strValue[pos] != 'Z') &&
-			 (strValue[pos] != '+') && (strValue[pos] != '-') && (strValue[pos] != 0) ) {
-			XMP_Throw ( "Invalid date string, after whole seconds", kXMPErr_BadParam );
-		}
-		if ( temp > 59 ) temp = 59;	// *** 1269463: XMP_Throw ( "Whole second is out of range", kXMPErr_BadParam );
-		binValue->second = temp;
-		// Don't check for done, we have to work up to the time zone.
-
-		if ( strValue[pos] == '.' ) {
-
-			++pos;
-			size_t digits = pos;	// Will be the number of digits later.
-
-			temp = GatherInt ( strValue, &pos, "Invalid fractional seconds in date string" );	// Extract the fractional seconds.
-			if ( (strValue[pos] != 'Z') && (strValue[pos] != '+') && (strValue[pos] != '-') && (strValue[pos] != 0) ) {
-				XMP_Throw ( "Invalid date string, after fractional second", kXMPErr_BadParam );
-			}
-
-			digits = pos - digits;
-			for ( ; digits > 9; --digits ) temp = temp / 10;
-			for ( ; digits < 9; ++digits ) temp = temp * 10;
-
-			if ( temp >= 1000*1000*1000 ) XMP_Throw ( "Fractional second is out of range", kXMPErr_BadParam );
-			binValue->nanoSecond = temp;
-			// Don't check for done, we have to work up to the time zone.
-
-		}
-
-	}
-
-	if ( strValue[pos] == 'Z' ) {
-
-		++pos;
-
-	} else if ( strValue[pos] != 0 ) {
-
-		if ( strValue[pos] == '+' ) {
-			binValue->tzSign = kXMP_TimeEastOfUTC;
-		} else if ( strValue[pos] == '-' ) {
-			binValue->tzSign = kXMP_TimeWestOfUTC;
-		} else {
-			XMP_Throw ( "Time zone must begin with 'Z', '+', or '-'", kXMPErr_BadParam );
-		}
-
-		++pos;
-		temp = GatherInt ( strValue, &pos, "Invalid time zone hour in date string" );	// Extract the time zone hour.
-		if ( strValue[pos] != ':' ) XMP_Throw ( "Invalid date string, after time zone hour", kXMPErr_BadParam );
-		if ( temp > 23 ) XMP_Throw ( "Time zone hour is out of range", kXMPErr_BadParam );
-		binValue->tzHour = temp;
-
-		++pos;
-		temp = GatherInt ( strValue, &pos, "Invalid time zone minute in date string" ); // Extract the time zone minute.
-		if ( temp > 59 ) XMP_Throw ( "Time zone minute is out of range", kXMPErr_BadParam );
-		binValue->tzMinute = temp;
-
-	} else {
-
-		XMPUtils::SetTimeZone( binValue );
-
-	}
-
-	if ( strValue[pos] != 0 ) XMP_Throw ( "Invalid date string, extra chars at end", kXMPErr_BadParam );
-
-}	// ConvertToDate
-
-
-// -------------------------------------------------------------------------------------------------
-// EncodeToBase64
-// --------------
-//
-// Encode a string of raw data bytes in base 64 according to RFC 2045. For the encoding definition
-// see section 6.8 in <http://www.ietf.org/rfc/rfc2045.txt>. Although it isn't needed for RDF, we
-// do insert a linefeed character as a newline for every 76 characters of encoded output.
-
-/* class static */ void
-XMPUtils::EncodeToBase64 ( XMP_StringPtr   rawStr,
-						   XMP_StringLen   rawLen,
-						   XMP_StringPtr * encodedStr,
-						   XMP_StringLen * encodedLen )
-{
-	if ( (rawStr == 0) && (rawLen != 0) ) XMP_Throw ( "Null raw data buffer", kXMPErr_BadParam );
-	if ( rawLen == 0 ) {
-		*encodedStr = 0;
-		*encodedLen = 0;
-		return;
-	}
-
-	char	encChunk[4];
-
-	unsigned long	in, out;
-	unsigned char	c1, c2, c3;
-	unsigned long	merge;
-
-	const size_t	outputSize	= (rawLen / 3) * 4; // Approximate, might be  small.
-
-	sBase64Str->erase();
-	sBase64Str->reserve ( outputSize );
-
-	// ----------------------------------------------------------------------------------------
-	// Each 6 bits of input produces 8 bits of output, so 3 input bytes become 4 output bytes.
-	// Process the whole chunks of 3 bytes first, then deal with any remainder. Be careful with
-	// the loop comparison, size-2 could be negative!
-
-	for ( in = 0, out = 0; (in+2) < rawLen; in += 3, out += 4 ) {
-
-		c1	= rawStr[in];
-		c2	= rawStr[in+1];
-		c3	= rawStr[in+2];
-
-		merge	= (c1 << 16) + (c2 << 8) + c3;
-
-		encChunk[0] = sBase64Chars [ merge >> 18 ];
-		encChunk[1] = sBase64Chars [ (merge >> 12) & 0x3F ];
-		encChunk[2] = sBase64Chars [ (merge >> 6) & 0x3F ];
-		encChunk[3] = sBase64Chars [ merge & 0x3F ];
-
-		if ( out >= 76 ) {
-			sBase64Str->append ( 1, kLF );
-			out = 0;
-		}
-		sBase64Str->append ( encChunk, 4 );
-
-	}
-
-	// ------------------------------------------------------------------------------------------
-	// The output must always be a multiple of 4 bytes. If there is a 1 or 2 byte input remainder
-	// we need to create another chunk. Zero pad with bits to a 6 bit multiple, then add one or
-	// two '=' characters to pad out to 4 bytes.
-
-	switch ( rawLen - in ) {
-
-		case 0:		// Done, no remainder.
-			break;
-
-		case 1:		// One input byte remains.
-
-			c1	= rawStr[in];
-			merge	= c1 << 16;
-
-			encChunk[0] = sBase64Chars [ merge >> 18 ];
-			encChunk[1] = sBase64Chars [ (merge >> 12) & 0x3F ];
-			encChunk[2] = encChunk[3] = '=';
-
-			if ( out >= 76 ) sBase64Str->append ( 1, kLF );
-			sBase64Str->append ( encChunk, 4 );
-			break;
-
-		case 2:		// Two input bytes remain.
-
-			c1	= rawStr[in];
-			c2	= rawStr[in+1];
-			merge	= (c1 << 16) + (c2 << 8);
-
-			encChunk[0] = sBase64Chars [ merge >> 18 ];
-			encChunk[1] = sBase64Chars [ (merge >> 12) & 0x3F ];
-			encChunk[2] = sBase64Chars [ (merge >> 6) & 0x3F ];
-			encChunk[3] = '=';
-
-			if ( out >= 76 ) sBase64Str->append ( 1, kLF );
-			sBase64Str->append ( encChunk, 4 );
-			break;
-
-	}
-
-	// -------------------------
-	// Assign the output values.
-
-	*encodedStr = sBase64Str->c_str();
-	*encodedLen = sBase64Str->size();
-
-}	// EncodeToBase64
-
-
-// -------------------------------------------------------------------------------------------------
-// DecodeFromBase64
-// ----------------
-//
-// Decode a string of raw data bytes from base 64 according to RFC 2045. For the encoding definition
-// see section 6.8 in <http://www.ietf.org/rfc/rfc2045.txt>. RFC 2045 talks about ignoring all "bad"
-// input but warning about non-whitespace. For XMP use we ignore space, tab, LF, and CR. Any other
-// bad input is rejected.
-
-/* class static */ void
-XMPUtils::DecodeFromBase64 ( XMP_StringPtr	 encodedStr,
-							 XMP_StringLen	 encodedLen,
-							 XMP_StringPtr * rawStr,
-							 XMP_StringLen * rawLen )
-{
-	if ( (encodedStr == 0) && (encodedLen != 0) ) XMP_Throw ( "Null encoded data buffer", kXMPErr_BadParam );
-	if ( encodedLen == 0 ) {
-		*rawStr = 0;
-		*rawLen = 0;
-		return;
-	}
-
-	unsigned char	ch, rawChunk[3];
-	unsigned long	inStr, inChunk, inLimit, merge, padding;
-
-	XMP_StringLen	outputSize	= (encodedLen / 4) * 3; // Only a close approximation.
-
-	sBase64Str->erase();
-	sBase64Str->reserve ( outputSize );
-
-
-	// ----------------------------------------------------------------------------------------
-	// Each 8 bits of input produces 6 bits of output, so 4 input bytes become 3 output bytes.
-	// Process all but the last 4 data bytes first, then deal with the final chunk. Whitespace
-	// in the input must be ignored. The first loop finds where the last 4 data bytes start and
-	// counts the number of padding equal signs.
-
-	padding = 0;
-	for ( inStr = 0, inLimit = encodedLen; (inStr < 4) && (inLimit > 0); ) {
-		inLimit -= 1;	// ! Don't do in the loop control, the decr/test order is wrong.
-		ch = encodedStr[inLimit];
-		if ( ch == '=' ) {
-			padding += 1;	// The equal sign padding is a data byte.
-		} else if ( DecodeBase64Char(ch) == 0xFF ) {
-			continue;	// Ignore whitespace, don't increment inStr.
-		} else {
-			inStr += 1;
-		}
-	}
-
-	// ! Be careful to count whitespace that is immediately before the final data. Otherwise
-	// ! middle portion will absorb the final data and mess up the final chunk processing.
-
-	while ( (inLimit > 0) && (DecodeBase64Char(encodedStr[inLimit-1]) == 0xFF) ) --inLimit;
-
-	if ( inStr == 0 ) return;	// Nothing but whitespace.
-	if ( padding > 2 ) XMP_Throw ( "Invalid encoded string", kXMPErr_BadParam );
-
-	// -------------------------------------------------------------------------------------------
-	// Now process all but the last chunk. The limit ensures that we have at least 4 data bytes
-	// left when entering the output loop, so the inner loop will succeed without overrunning the
-	// end of the data. At the end of the outer loop we might be past inLimit though.
-
-	inStr = 0;
-	while ( inStr < inLimit ) {
-
-		merge = 0;
-		for ( inChunk = 0; inChunk < 4; ++inStr ) { // ! Yes, increment inStr on each pass.
-			ch = DecodeBase64Char ( encodedStr [inStr] );
-			if ( ch == 0xFF ) continue; // Ignore whitespace.
-			merge = (merge << 6) + ch;
-			inChunk += 1;
-		}
-
-		rawChunk[0] = (unsigned char) (merge >> 16);
-		rawChunk[1] = (unsigned char) ((merge >> 8) & 0xFF);
-		rawChunk[2] = (unsigned char) (merge & 0xFF);
-
-		sBase64Str->append ( (char*)rawChunk, 3 );
-
-	}
-
-	// -------------------------------------------------------------------------------------------
-	// Process the final, possibly partial, chunk of data. The input is always a multiple 4 bytes,
-	// but the raw data can be any length. The number of padding '=' characters determines if the
-	// final chunk has 1, 2, or 3 raw data bytes.
-
-	XMP_Assert ( inStr < encodedLen );
-
-	merge = 0;
-	for ( inChunk = 0; inChunk < 4-padding; ++inStr ) { // ! Yes, increment inStr on each pass.
-		ch = DecodeBase64Char ( encodedStr[inStr] );
-		if ( ch == 0xFF ) continue; // Ignore whitespace.
-		merge = (merge << 6) + ch;
-		inChunk += 1;
-	}
-
-	if ( padding == 2 ) {
-
-		rawChunk[0] = (unsigned char) (merge >> 4);
-		sBase64Str->append ( (char*)rawChunk, 1 );
-
-	} else if ( padding == 1 ) {
-
-		rawChunk[0] = (unsigned char) (merge >> 10);
-		rawChunk[1] = (unsigned char) ((merge >> 2) & 0xFF);
-		sBase64Str->append ( (char*)rawChunk, 2 );
-
-	} else {
-
-		rawChunk[0] = (unsigned char) (merge >> 16);
-		rawChunk[1] = (unsigned char) ((merge >> 8) & 0xFF);
-		rawChunk[2] = (unsigned char) (merge & 0xFF);
-		sBase64Str->append ( (char*)rawChunk, 3 );
-
-	}
-
-	// -------------------------
-	// Assign the output values.
-
-	*rawStr = sBase64Str->c_str();
-	*rawLen = sBase64Str->size();
-
-}	// DecodeFromBase64
-
-
-// -------------------------------------------------------------------------------------------------
-// PackageForJPEG
-// --------------
-
-/* class static */ void
-XMPUtils::PackageForJPEG ( const XMPMeta & origXMP,
-						   XMP_StringPtr * stdStr,
-						   XMP_StringLen * stdLen,
-						   XMP_StringPtr * extStr,
-						   XMP_StringLen * extLen,
-						   XMP_StringPtr * digestStr,
-						   XMP_StringLen * digestLen )
-{
-	enum { kStdXMPLimit = 65000 };
-	static const char * kPacketTrailer = "<?xpacket end=\"w\"?>";
-	static size_t kTrailerLen = strlen ( kPacketTrailer );
-
-	XMP_StringPtr tempStr;
-	XMP_StringLen tempLen;
-
-	XMPMeta stdXMP, extXMP;
-
-	sStandardXMP->clear();	// Clear the static strings that get returned to the client.
-	sExtendedXMP->clear();
-	sExtendedDigest->clear();
-
-	XMP_OptionBits keepItSmall = kXMP_UseCompactFormat | kXMP_OmitAllFormatting;
-
-	// Try to serialize everything. Note that we're making internal calls to SerializeToBuffer, so
-	// we'll be getting back the pointer and length for its internal string.
-
-	origXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
-	#if Trace_PackageForJPEG
-		printf ( "\nXMPUtils::PackageForJPEG - Full serialize %d bytes\n", tempLen );
-	#endif
-
-	if ( tempLen > kStdXMPLimit ) {
-
-		// Couldn't fit everything, make a copy of the input XMP and make sure there is no xmp:Thumbnails property.
-
-		stdXMP.tree.options = origXMP.tree.options;
-		stdXMP.tree.name    = origXMP.tree.name;
-		stdXMP.tree.value   = origXMP.tree.value;
-		CloneOffspring ( &origXMP.tree, &stdXMP.tree );
-
-		if ( stdXMP.DoesPropertyExist ( kXMP_NS_XMP, "Thumbnails" ) ) {
-			stdXMP.DeleteProperty ( kXMP_NS_XMP, "Thumbnails" );
-			stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
-			#if Trace_PackageForJPEG
-				printf ( "  Delete xmp:Thumbnails, %d bytes left\n", tempLen );
-			#endif
-		}
-
-	}
-
-	if ( tempLen > kStdXMPLimit ) {
-
-		// Still doesn't fit, move all of the Camera Raw namespace. Add a dummy value for xmpNote:HasExtendedXMP.
-
-		stdXMP.SetProperty ( kXMP_NS_XMP_Note, "HasExtendedXMP", "123456789-123456789-123456789-12", 0 );
-
-		XMP_NodePtrPos crSchemaPos;
-		XMP_Node * crSchema = FindSchemaNode ( &stdXMP.tree, kXMP_NS_CameraRaw, kXMP_ExistingOnly, &crSchemaPos );
-
-		if ( crSchema != 0 ) {
-			crSchema->parent = &extXMP.tree;
-			extXMP.tree.children.push_back ( crSchema );
-			stdXMP.tree.children.erase ( crSchemaPos );
-			stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
-			#if Trace_PackageForJPEG
-				printf ( "  Move Camera Raw schema, %d bytes left\n", tempLen );
-			#endif
-		}
-
-	}
-
-	if ( tempLen > kStdXMPLimit ) {
-
-		// Still doesn't fit, move photoshop:History.
-
-		bool moved = MoveOneProperty ( stdXMP, &extXMP, kXMP_NS_Photoshop, "photoshop:History" );
-
-		if ( moved ) {
-			stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
-			#if Trace_PackageForJPEG
-				printf ( "  Move photoshop:History, %d bytes left\n", tempLen );
-			#endif
-		}
-
-	}
-
-	if ( tempLen > kStdXMPLimit ) {
-
-		// Still doesn't fit, move top level properties in order of estimated size. This is done by
-		// creating a multi-map that maps the serialized size to the string pair for the schema URI
-		// and top level property name. Since maps are inherently ordered, a reverse iteration of
-		// the map can be done to move the largest things first. We use a double loop to keep going
-		// until the serialization actually fits, in case the estimates are off.
-
-		PropSizeMap propSizes;
-		CreateEstimatedSizeMap ( stdXMP, &propSizes );
-
-		#if Trace_PackageForJPEG
-		if ( ! propSizes.empty() ) {
-			printf ( "  Top level property map, smallest to largest:\n" );
-			PropSizeMap::iterator mapPos = propSizes.begin();
-			PropSizeMap::iterator mapEnd = propSizes.end();
-			for ( ; mapPos != mapEnd; ++mapPos ) {
-				size_t propSize = mapPos->first;
-				const char * schemaName = mapPos->second.first->c_str();
-				const char * propName   = mapPos->second.second->c_str();
-				printf ( "    %d bytes, %s in %s\n", propSize, propName, schemaName );
-			}
-		}
-		#endif
-
-		#if 0	// Trace_PackageForJPEG		*** Xcode 2.3 on 10.4.7 has bugs in backwards iteration
-		if ( ! propSizes.empty() ) {
-			printf ( "  Top level property map, largest to smallest:\n" );
-			PropSizeMap::iterator mapPos   = propSizes.end();
-			PropSizeMap::iterator mapBegin = propSizes.begin();
-			for ( --mapPos; true; --mapPos ) {
-				size_t propSize = mapPos->first;
-				const char * schemaName = mapPos->second.first->c_str();
-				const char * propName   = mapPos->second.second->c_str();
-				printf ( "    %d bytes, %s in %s\n", propSize, propName, schemaName );
-				if ( mapPos == mapBegin ) break;
-			}
-		}
-		#endif
-
-		// Outer loop to make sure enough is actually moved.
-
-		while ( (tempLen > kStdXMPLimit) && (! propSizes.empty()) ) {
-
-			// Inner loop, move what seems to be enough according to the estimates.
-
-			while ( (tempLen > kStdXMPLimit) && (! propSizes.empty()) ) {
-
-				size_t propSize = MoveLargestProperty ( stdXMP, &extXMP, propSizes );
-				XMP_Assert ( propSize > 0 );
-
-				if ( propSize > tempLen ) propSize = tempLen;	// ! Don't go negative.
-				tempLen -= propSize;
-
-			}
-
-			// Reserialize the remaining standard XMP.
-
-			stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
-
-		}
-
-	}
-
-	if ( tempLen > kStdXMPLimit ) {
-		// Still doesn't fit, throw an exception and let the client decide what to do.
-		// ! This should never happen with the policy of moving any and all top level properties.
-		XMP_Throw ( "Can't reduce XMP enough for JPEG file", kXMPErr_TooLargeForJPEG );
-	}
-
-	// Set the static output strings.
-
-	if ( extXMP.tree.children.empty() ) {
-
-		// Just have the standard XMP.
-		sStandardXMP->assign ( tempStr, tempLen );
-
-	} else {
-
-		// Have extended XMP. Serialize it, compute the digest, reset xmpNote:HasExtendedXMP, and
-		// reserialize the standard XMP.
-
-		extXMP.SerializeToBuffer ( &tempStr, &tempLen, (keepItSmall | kXMP_OmitPacketWrapper), 0, "", "", 0 );
-		sExtendedXMP->assign ( tempStr, tempLen );
-
-		MD5_CTX  context;
-		XMP_Uns8 digest [16];
-		MD5Init ( &context );
-		MD5Update ( &context, (XMP_Uns8*)tempStr, tempLen );
-		MD5Final ( digest, &context );
-
-		sExtendedDigest->reserve ( 32 );
-		for ( size_t i = 0; i < 16; ++i ) {
-			XMP_Uns8 byte = digest[i];
-			sExtendedDigest->push_back ( kHexDigits [ byte>>4 ] );
-			sExtendedDigest->push_back ( kHexDigits [ byte&0xF ] );
-		}
-
-		stdXMP.SetProperty ( kXMP_NS_XMP_Note, "HasExtendedXMP", sExtendedDigest->c_str(), 0 );
-		stdXMP.SerializeToBuffer ( &tempStr, &tempLen, keepItSmall, 1, "", "", 0 );
-		sStandardXMP->assign ( tempStr, tempLen );
-
-	}
-
-	// Adjust the standard XMP padding to be up to 2KB.
-
-	XMP_Assert ( (sStandardXMP->size() > kTrailerLen) && (sStandardXMP->size() <= kStdXMPLimit) );
-	const char * packetEnd = 0;
-    packetEnd = sStandardXMP->c_str() + sStandardXMP->size() - kTrailerLen;
-	XMP_Assert ( XMP_LitMatch ( packetEnd, kPacketTrailer ) );
-	UNUSED(packetEnd);
-
-	size_t extraPadding = kStdXMPLimit - sStandardXMP->size();	// ! Do this before erasing the trailer.
-	if ( extraPadding > 2047 ) extraPadding = 2047;
-	sStandardXMP->erase ( sStandardXMP->size() - kTrailerLen );
-	sStandardXMP->append ( extraPadding, ' ' );
-	sStandardXMP->append ( kPacketTrailer );
-
-	// Assign the output pointer and sizes.
-
-	*stdStr = sStandardXMP->c_str();
-	*stdLen = sStandardXMP->size();
-	*extStr = sExtendedXMP->c_str();
-	*extLen = sExtendedXMP->size();
-	*digestStr = sExtendedDigest->c_str();
-	*digestLen = sExtendedDigest->size();
-
-}	// PackageForJPEG
-
-
-// -------------------------------------------------------------------------------------------------
-// MergeFromJPEG
-// -------------
-//
-// Copy all of the top level properties from extendedXMP to fullXMP, replacing any duplicates.
-// Delete the xmpNote:HasExtendedXMP property from fullXMP.
-
-/* class static */ void
-XMPUtils::MergeFromJPEG ( XMPMeta *       fullXMP,
-                          const XMPMeta & extendedXMP )
-{
-
-	XMPUtils::AppendProperties ( extendedXMP, fullXMP, kXMPUtil_DoAllProperties );
-	fullXMP->DeleteProperty ( kXMP_NS_XMP_Note, "HasExtendedXMP" );
-
-}	// MergeFromJPEG
-
-
-// -------------------------------------------------------------------------------------------------
-// CurrentDateTime
-// ---------------
-
-/* class static */ void
-XMPUtils::CurrentDateTime ( XMP_DateTime * xmpTime )
-{
-	XMP_Assert ( xmpTime != 0 );	// ! Enforced by wrapper.
-
-	ansi_tt binTime = ansi_time(0);
-	if ( binTime == -1 ) XMP_Throw ( "Failure from ANSI C time function", kXMPErr_ExternalFailure );
-	ansi_tm currTime;
-	ansi_localtime ( &binTime, &currTime );
-
-	xmpTime->year = currTime.tm_year + 1900;
-	xmpTime->month = currTime.tm_mon + 1;
-	xmpTime->day = currTime.tm_mday;
-	xmpTime->hour = currTime.tm_hour;
-	xmpTime->minute = currTime.tm_min;
-	xmpTime->second = currTime.tm_sec;
-
-	xmpTime->nanoSecond = 0;
-	xmpTime->tzSign = 0;
-	xmpTime->tzHour = 0;
-	xmpTime->tzMinute = 0;
-
-	XMPUtils::SetTimeZone ( xmpTime );
-
-}	// CurrentDateTime
-
-
-// -------------------------------------------------------------------------------------------------
-// SetTimeZone
-// -----------
-//
-// Sets just the time zone part of the time.  Useful for determining the local time zone or for
-// converting a "zone-less" time to a proper local time. The ANSI C time functions are smart enough
-// to do all the right stuff, as long as we call them properly!
-
-/* class static */ void
-XMPUtils::SetTimeZone ( XMP_DateTime * xmpTime )
-{
-	XMP_Assert ( xmpTime != 0 );	// ! Enforced by wrapper.
-
-	if ( (xmpTime->tzSign != 0) || (xmpTime->tzHour != 0) || (xmpTime->tzMinute != 0) ) {
-		XMP_Throw ( "SetTimeZone can only be used on \"zoneless\" times", kXMPErr_BadParam );
-	}
-
-	// Create ansi_tt form of the input time. Need the ansi_tm form to make the ansi_tt form.
-
-	ansi_tt ttTime;
-	ansi_tm tmLocal, tmUTC;
-
-	if ( (xmpTime->year == 0) && (xmpTime->month == 0) && (xmpTime->day == 0) ) {
-		ansi_tt now = ansi_time(0);
-		if ( now == -1 ) XMP_Throw ( "Failure from ANSI C time function", kXMPErr_ExternalFailure );
-		ansi_localtime ( &now, &tmLocal );
-	} else {
-		tmLocal.tm_year = xmpTime->year - 1900;
-		while ( tmLocal.tm_year < 70 ) tmLocal.tm_year += 4;	// ! Some versions of mktime barf on years before 1970.
-		tmLocal.tm_mon	 = xmpTime->month - 1;
-		tmLocal.tm_mday	 = xmpTime->day;
-	}
-
-	tmLocal.tm_hour = xmpTime->hour;
-	tmLocal.tm_min = xmpTime->minute;
-	tmLocal.tm_sec = xmpTime->second;
-	tmLocal.tm_isdst = -1;	// Don't know if daylight time is in effect.
-
-	ttTime = ansi_mktime ( &tmLocal );
-	if ( ttTime == -1 ) XMP_Throw ( "Failure from ANSI C mktime function", kXMPErr_ExternalFailure );
-
-	// Convert back to a localized ansi_tm time and get the corresponding UTC ansi_tm time.
-
-	ansi_localtime ( &ttTime, &tmLocal );
-	ansi_gmtime ( &ttTime, &tmUTC );
-
-	// Get the offset direction and amount.
-
-	ansi_tm tmx = tmLocal;	// ! Note that mktime updates the ansi_tm parameter, messing up difftime!
-	ansi_tm tmy = tmUTC;
-	tmx.tm_isdst = tmy.tm_isdst = 0;
-	ansi_tt ttx = ansi_mktime ( &tmx );
-	ansi_tt tty = ansi_mktime ( &tmy );
-	double diffSecs;
-
-	if ( (ttx != -1) && (tty != -1) ) {
-		diffSecs = ansi_difftime ( ttx, tty );
-	} else {
-		#if XMP_MacBuild
-			// Looks like Apple's mktime is buggy - see W1140533. But the offset is visible.
-			diffSecs = tmLocal.tm_gmtoff;
-		#else
-			// Win and UNIX don't have a visible offset. Make sure we know about the failure,
-			// then try using the current date/time as a close fallback.
-			ttTime = ansi_time(0);
-			if ( ttTime == -1 ) XMP_Throw ( "Failure from ANSI C time function", kXMPErr_ExternalFailure );
-			ansi_localtime ( &ttTime, &tmx );
-			ansi_gmtime ( &ttTime, &tmy );
-			tmx.tm_isdst = tmy.tm_isdst = 0;
-			ttx = ansi_mktime ( &tmx );
-			tty = ansi_mktime ( &tmy );
-			if ( (ttx == -1) || (tty == -1) ) XMP_Throw ( "Failure from ANSI C mktime function", kXMPErr_ExternalFailure );
-			diffSecs = ansi_difftime ( ttx, tty );
-		#endif
-	}
-
-	if ( diffSecs > 0.0 ) {
-		xmpTime->tzSign = kXMP_TimeEastOfUTC;
-	} else if ( diffSecs == 0.0 ) {
-		xmpTime->tzSign = kXMP_TimeIsUTC;
-	} else {
-		xmpTime->tzSign = kXMP_TimeWestOfUTC;
-		diffSecs = -diffSecs;
-	}
-	xmpTime->tzHour = XMP_Int32 ( diffSecs / 3600.0 );
-	xmpTime->tzMinute = XMP_Int32 ( (diffSecs / 60.0) - (xmpTime->tzHour * 60.0) );
-
-	// *** Save the tm_isdst flag in a qualifier?
-
-	XMP_Assert ( (0 <= xmpTime->tzHour) && (xmpTime->tzHour <= 23) );
-	XMP_Assert ( (0 <= xmpTime->tzMinute) && (xmpTime->tzMinute <= 59) );
-	XMP_Assert ( (-1 <= xmpTime->tzSign) && (xmpTime->tzSign <= +1) );
-	XMP_Assert ( (xmpTime->tzSign == 0) ? ((xmpTime->tzHour == 0) && (xmpTime->tzMinute == 0)) :
-										  ((xmpTime->tzHour != 0) || (xmpTime->tzMinute != 0)) );
-
-}	// SetTimeZone
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertToUTCTime
-// ----------------
-
-/* class static */ void
-XMPUtils::ConvertToUTCTime ( XMP_DateTime * time )
-{
-	XMP_Assert ( time != 0 );	// ! Enforced by wrapper.
-
-	XMP_Assert ( (0 <= time->tzHour) && (time->tzHour <= 23) );
-	XMP_Assert ( (0 <= time->tzMinute) && (time->tzMinute <= 59) );
-	XMP_Assert ( (-1 <= time->tzSign) && (time->tzSign <= +1) );
-	XMP_Assert ( (time->tzSign == 0) ? ((time->tzHour == 0) && (time->tzMinute == 0)) :
-									   ((time->tzHour != 0) || (time->tzMinute != 0)) );
-
-	if ( time->tzSign == kXMP_TimeEastOfUTC ) {
-		// We are before (east of) GMT, subtract the offset from the time.
-		time->hour -= time->tzHour;
-		time->minute -= time->tzMinute;
-	} else if ( time->tzSign == kXMP_TimeWestOfUTC ) {
-		// We are behind (west of) GMT, add the offset to the time.
-		time->hour += time->tzHour;
-		time->minute += time->tzMinute;
-	}
-
-	AdjustTimeOverflow ( time );
-	time->tzSign = time->tzHour = time->tzMinute = 0;
-
-}	// ConvertToUTCTime
-
-
-// -------------------------------------------------------------------------------------------------
-// ConvertToLocalTime
-// ------------------
-
-/* class static */ void
-XMPUtils::ConvertToLocalTime ( XMP_DateTime * time )
-{
-	XMP_Assert ( time != 0 );	// ! Enforced by wrapper.
-
-	XMP_Assert ( (0 <= time->tzHour) && (time->tzHour <= 23) );
-	XMP_Assert ( (0 <= time->tzMinute) && (time->tzMinute <= 59) );
-	XMP_Assert ( (-1 <= time->tzSign) && (time->tzSign <= +1) );
-	XMP_Assert ( (time->tzSign == 0) ? ((time->tzHour == 0) && (time->tzMinute == 0)) :
-									   ((time->tzHour != 0) || (time->tzMinute != 0)) );
-
-	ConvertToUTCTime ( time );	// The existing time zone might not be the local one.
-	SetTimeZone ( time );		// Fill in the local timezone offset, then adjust the time.
-
-	if ( time->tzSign > 0 ) {
-		// We are before (east of) GMT, add the offset to the time.
-		time->hour += time->tzHour;
-		time->minute += time->tzMinute;
-	} else if ( time->tzSign < 0 ) {
-		// We are behind (west of) GMT, subtract the offset from the time.
-		time->hour -= time->tzHour;
-		time->minute -= time->tzMinute;
-	}
-
-	AdjustTimeOverflow ( time );
-
-}	// ConvertToLocalTime
-
-
-// -------------------------------------------------------------------------------------------------
-// CompareDateTime
-// ---------------
-
-/* class static */ int
-XMPUtils::CompareDateTime ( const XMP_DateTime & _in_left,
-							const XMP_DateTime & _in_right )
-{
-	int result;
-
-	XMP_DateTime left  = _in_left;
-	XMP_DateTime right = _in_right;
-
-	ConvertToUTCTime ( &left );
-	ConvertToUTCTime ( &right );
-
-	// *** We could use memcmp if the XMP_DateTime stuct has no holes.
-
-	if ( left.year < right.year ) {
-		result = -1;
-	} else if ( left.year > right.year ) {
-		result = +1;
-	} else if ( left.month < right.month ) {
-		result = -1;
-	} else if ( left.month > right.month ) {
-		result = +1;
-	} else if ( left.day < right.day ) {
-		result = -1;
-	} else if ( left.day > right.day ) {
-		result = +1;
-	} else if ( left.hour < right.hour ) {
-		result = -1;
-	} else if ( left.hour > right.hour ) {
-		result = +1;
-	} else if ( left.minute < right.minute ) {
-		result = -1;
-	} else if ( left.minute > right.minute ) {
-		result = +1;
-	} else if ( left.second < right.second ) {
-		result = -1;
-	} else if ( left.second > right.second ) {
-		result = +1;
-	} else if ( left.nanoSecond < right.nanoSecond ) {
-		result = -1;
-	} else if ( left.nanoSecond > right.nanoSecond ) {
-		result = +1;
-	} else {
-		result = 0;
-	}
-
-	return result;
-
-}	// CompareDateTime
-
-// =================================================================================================
diff --git a/xmpsdk/src/XMPUtils.hpp b/xmpsdk/src/XMPUtils.hpp
deleted file mode 100644
index e1c7e78d..00000000
--- a/xmpsdk/src/XMPUtils.hpp
+++ /dev/null
@@ -1,221 +0,0 @@
-#ifndef __XMPUtils_hpp__
-#define __XMPUtils_hpp__
-
-// =================================================================================================
-// Copyright 2002-2007 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:	Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-
-#include "XMP_Environment.h"
-#include "XMP_Const.h"
-
-#include "XMPMeta.hpp"
-#include "XMPCore_Impl.hpp"
-#include "client-glue/WXMPUtils.hpp"
-
-// -------------------------------------------------------------------------------------------------
-
-extern XMP_VarString * sComposedPath;		// *** Only really need 1 string. Shrink periodically?
-extern XMP_VarString * sConvertedValue;
-extern XMP_VarString * sBase64Str;
-extern XMP_VarString * sCatenatedItems;
-extern XMP_VarString * sStandardXMP;
-extern XMP_VarString * sExtendedXMP;
-extern XMP_VarString * sExtendedDigest;
-
-// -------------------------------------------------------------------------------------------------
-
-class	XMPUtils {
-public:
-	
-	static bool
-	Initialize();	// ! For internal use only!
-	
-	static void
-	Terminate() RELEASE_NO_THROW;	// ! For internal use only!
-
-	static void
-	Unlock ( XMP_OptionBits options );
-
-	// ---------------------------------------------------------------------------------------------
-
-	static void
-	ComposeArrayItemPath ( XMP_StringPtr   schemaNS,
-						   XMP_StringPtr   arrayName,
-						   XMP_Index	   itemIndex,
-						   XMP_StringPtr * fullPath,
-						   XMP_StringLen * pathSize );
-
-	static void
-	ComposeStructFieldPath ( XMP_StringPtr	 schemaNS,
-							 XMP_StringPtr	 structName,
-							 XMP_StringPtr	 fieldNS,
-							 XMP_StringPtr	 fieldName,
-							 XMP_StringPtr * fullPath,
-							 XMP_StringLen * pathSize );
-
-	static void
-	ComposeQualifierPath ( XMP_StringPtr   schemaNS,
-						   XMP_StringPtr   propName,
-						   XMP_StringPtr   qualNS,
-						   XMP_StringPtr   qualName,
-						   XMP_StringPtr * fullPath,
-						   XMP_StringLen * pathSize );
-
-	static void
-	ComposeLangSelector ( XMP_StringPtr		schemaNS,
-						  XMP_StringPtr		arrayName,
-						  XMP_StringPtr		langName,
-						  XMP_StringPtr *	fullPath,
-						  XMP_StringLen *	pathSize );
-
-	static void
-	ComposeFieldSelector ( XMP_StringPtr   schemaNS,
-						   XMP_StringPtr   arrayName,
-						   XMP_StringPtr   fieldNS,
-						   XMP_StringPtr   fieldName,
-						   XMP_StringPtr   fieldValue,
-						   XMP_StringPtr * fullPath,
-						   XMP_StringLen * pathSize );
-
-	// ---------------------------------------------------------------------------------------------
-
-	static void
-	ConvertFromBool ( bool			  binValue,
-					  XMP_StringPtr * strValue,
-					  XMP_StringLen * strSize );
-
-	static void
-	ConvertFromInt ( XMP_Int32		 binValue,
-					 XMP_StringPtr	 format,
-					 XMP_StringPtr * strValue,
-					 XMP_StringLen * strSize );
-
-	static void
-	ConvertFromInt64 ( XMP_Int64	   binValue,
-					   XMP_StringPtr   format,
-					   XMP_StringPtr * strValue,
-					   XMP_StringLen * strSize );
-
-	static void
-	ConvertFromFloat ( double		   binValue,
-					   XMP_StringPtr   format,
-					   XMP_StringPtr * strValue,
-					   XMP_StringLen * strSize );
-
-	static void
-	ConvertFromDate ( const XMP_DateTime & binValue,
-					  XMP_StringPtr *	   strValue,
-					  XMP_StringLen *	   strSize );
-
-	// ---------------------------------------------------------------------------------------------
-
-	static bool
-	ConvertToBool ( XMP_StringPtr strValue );
-
-	static XMP_Int32
-	ConvertToInt ( XMP_StringPtr strValue );
-
-	static XMP_Int64
-	ConvertToInt64 ( XMP_StringPtr strValue );
-
-	static double
-	ConvertToFloat ( XMP_StringPtr strValue );
-
-	static void
-	ConvertToDate  ( XMP_StringPtr	strValue,
-					 XMP_DateTime * binValue );
-
-	// ---------------------------------------------------------------------------------------------
-
-	static void
-	CurrentDateTime ( XMP_DateTime * time );
-
-	static void
-	SetTimeZone ( XMP_DateTime * time );
-
-	static void
-	ConvertToUTCTime ( XMP_DateTime * time );
-
-	static void
-	ConvertToLocalTime ( XMP_DateTime * time );
-
-	static int
-	CompareDateTime ( const XMP_DateTime & left,
-					  const XMP_DateTime & right );
-	// ---------------------------------------------------------------------------------------------
-
-	static void
-	EncodeToBase64 ( XMP_StringPtr	 rawStr,
-					 XMP_StringLen	 rawLen,
-					 XMP_StringPtr * encodedStr,
-					 XMP_StringLen * encodedLen );
-
-	static void
-	DecodeFromBase64 ( XMP_StringPtr   encodedStr,
-					   XMP_StringLen   encodedLen,
-					   XMP_StringPtr * rawStr,
-					   XMP_StringLen * rawLen );
-
-	// ---------------------------------------------------------------------------------------------
-
-	static void
-	PackageForJPEG ( const XMPMeta & xmpObj,
-					 XMP_StringPtr * stdStr,
-					 XMP_StringLen * stdLen,
-					 XMP_StringPtr * extStr,
-					 XMP_StringLen * extLen,
-					 XMP_StringPtr * digestStr,
-					 XMP_StringLen * digestLen );
-
-	static void
-	MergeFromJPEG ( XMPMeta *       fullXMP,
-                    const XMPMeta & extendedXMP );
-
-	// ---------------------------------------------------------------------------------------------
-
-	static void
-	CatenateArrayItems ( const XMPMeta & xmpObj,
-						 XMP_StringPtr	 schemaNS,
-						 XMP_StringPtr	 arrayName,
-						 XMP_StringPtr	 separator,
-						 XMP_StringPtr	 quotes,
-						 XMP_OptionBits	 options,
-						 XMP_StringPtr * catedStr,
-						 XMP_StringLen * catedLen );
-
-	static void
-	SeparateArrayItems ( XMPMeta *		xmpObj,
-						 XMP_StringPtr	schemaNS,
-						 XMP_StringPtr	arrayName,
-						 XMP_OptionBits options,
-						 XMP_StringPtr	catedStr );
-
-	static void
-	RemoveProperties ( XMPMeta *	  xmpObj,
-					   XMP_StringPtr  schemaNS,
-					   XMP_StringPtr  propName,
-					   XMP_OptionBits options );
-
-	static void
-	AppendProperties ( const XMPMeta & source,
-					   XMPMeta *	   dest,
-					   XMP_OptionBits  options );
-
-	static void
-	DuplicateSubtree ( const XMPMeta & source,
-					   XMPMeta *	   dest,
-					   XMP_StringPtr   sourceNS,
-					   XMP_StringPtr   sourceRoot,
-					   XMP_StringPtr   destNS,
-					   XMP_StringPtr   destRoot,
-					   XMP_OptionBits  options );
-
-};	// XMPUtils
-
-// =================================================================================================
-
-#endif	// __XMPUtils_hpp__
diff --git a/xmpsdk/src/XMP_BuildInfo.h b/xmpsdk/src/XMP_BuildInfo.h
deleted file mode 100644
index 2b387c86..00000000
--- a/xmpsdk/src/XMP_BuildInfo.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef __XMP_BuildInfo_h__
-#define __XMP_BuildInfo_h__ 1
-
-/* --------------------------------------------------------------------------------------------- */
-/* ** IMPORTANT ** This file must be usable by strict ANSI C compilers. No "//" comments, etc.   */
-/* --------------------------------------------------------------------------------------------- */
-
-/*
-// =================================================================================================
-// Copyright 2002-2008 Adobe Systems Incorporated
-// All Rights Reserved.
-//
-// NOTICE:  Adobe permits you to use, modify, and distribute this file in accordance with the terms
-// of the Adobe license agreement accompanying it.
-// =================================================================================================
-*/
-
-#define kXMP_Copyright Copyright (c) 2002-2008, Adobe Systems Incorporated
-#define kXMP_CopyrightStr "Copyright (c) 2002-2008, Adobe Systems Incorporated"
-#define kXMP_AdobeIPStr "<AdobeIP#0000425>"
-
-#endif	/* __XMP_BuildInfo_h__ */
-- 
2.11.0

