# HG changeset patch # User Sebastien Jodogne # Date 1405694470 -7200 # Node ID 0bfeeb6d340f8a96a7d86ab2d82c9c808cb5bfe2 # Parent 6d90e2bcab608e50be6635e4e769fa88b2b01ad2 json to xml conversion with pugixml diff -r 6d90e2bcab60 -r 0bfeeb6d340f CMakeLists.txt --- a/CMakeLists.txt Thu Jul 17 16:01:41 2014 +0200 +++ b/CMakeLists.txt Fri Jul 18 16:41:10 2014 +0200 @@ -21,9 +21,6 @@ SET(ENABLE_JPEG ON CACHE BOOL "Enable JPEG decompression") SET(ENABLE_JPEG_LOSSLESS ON CACHE BOOL "Enable JPEG-LS (Lossless) decompression") -# Experimental options -SET(USE_PLUSTACHE OFF CACHE BOOL "Use the Plustache templating engine (experimental)") - # Advanced parameters to fine-tune linking against system libraries SET(USE_SYSTEM_JSONCPP ON CACHE BOOL "Use the system version of JsonCpp") SET(USE_SYSTEM_GOOGLE_LOG ON CACHE BOOL "Use the system version of Google Log") @@ -37,7 +34,12 @@ SET(USE_SYSTEM_CURL ON CACHE BOOL "Use the system version of LibCurl") SET(USE_SYSTEM_OPENSSL ON CACHE BOOL "Use the system version of OpenSSL") SET(USE_SYSTEM_ZLIB ON CACHE BOOL "Use the system version of ZLib") + +# Experimental options +SET(USE_PLUSTACHE OFF CACHE BOOL "Use the Plustache templating engine (experimental)") +SET(USE_PUGIXML OFF CACHE BOOL "Use the Pugixml parser (experimental)") SET(USE_SYSTEM_PLUSTACHE OFF CACHE BOOL "Use the system version of Plustache (experimental)") +SET(USE_SYSTEM_PUGIXML OFF CACHE BOOL "Use the system version of Pugixml (experimental)") # Distribution-specific settings SET(USE_GTEST_DEBIAN_SOURCE_PACKAGE OFF CACHE BOOL "Use the sources of Google Test shipped with libgtest-dev (Debian only)") @@ -223,6 +225,7 @@ include(${CMAKE_SOURCE_DIR}/Resources/CMake/LuaConfiguration.cmake) include(${CMAKE_SOURCE_DIR}/Resources/CMake/LibCurlConfiguration.cmake) include(${CMAKE_SOURCE_DIR}/Resources/CMake/PlustacheConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/PugixmlConfiguration.cmake) if (${ENABLE_SSL}) diff -r 6d90e2bcab60 -r 0bfeeb6d340f Core/PrecompiledHeaders.h --- a/Core/PrecompiledHeaders.h Thu Jul 17 16:01:41 2014 +0200 +++ b/Core/PrecompiledHeaders.h Fri Jul 18 16:41:10 2014 +0200 @@ -49,6 +49,10 @@ #include #include +#if ORTHANC_PUGIXML_ENABLED == 1 +#include +#endif + #include "Enumerations.h" #include "OrthancException.h" #include "Toolbox.h" diff -r 6d90e2bcab60 -r 0bfeeb6d340f Core/Toolbox.cpp --- a/Core/Toolbox.cpp Thu Jul 17 16:01:41 2014 +0200 +++ b/Core/Toolbox.cpp Fri Jul 18 16:41:10 2014 +0200 @@ -83,6 +83,12 @@ #endif +#if ORTHANC_PUGIXML_ENABLED == 1 +#include "ChunkedBuffer.h" +#include +#endif + + namespace Orthanc { static bool finish; @@ -824,5 +830,126 @@ return boost::filesystem::exists(path); } + +#if ORTHANC_PUGIXML_ENABLED == 1 + class ChunkedBufferWriter : public pugi::xml_writer + { + private: + ChunkedBuffer buffer_; + + public: + virtual void write(const void *data, size_t size) + { + if (size > 0) + { + buffer_.AddChunk(reinterpret_cast(data), size); + } + } + + void Flatten(std::string& s) + { + buffer_.Flatten(s); + } + }; + + + static void JsonToXmlInternal(pugi::xml_node& target, + const Json::Value& source, + const std::string& arrayElement) + { + // http://jsoncpp.sourceforge.net/value_8h_source.html#l00030 + + switch (source.type()) + { + case Json::nullValue: + { + target.append_child(pugi::node_pcdata).set_value("null"); + break; + } + + case Json::intValue: + { + std::string s = boost::lexical_cast(source.asInt()); + target.append_child(pugi::node_pcdata).set_value(s.c_str()); + break; + } + + case Json::uintValue: + { + std::string s = boost::lexical_cast(source.asUInt()); + target.append_child(pugi::node_pcdata).set_value(s.c_str()); + break; + } + + case Json::realValue: + { + std::string s = boost::lexical_cast(source.asFloat()); + target.append_child(pugi::node_pcdata).set_value(s.c_str()); + break; + } + + case Json::stringValue: + { + target.append_child(pugi::node_pcdata).set_value(source.asString().c_str()); + break; + } + + case Json::booleanValue: + { + target.append_child(pugi::node_pcdata).set_value(source.asBool() ? "true" : "false"); + break; + } + + case Json::arrayValue: + { + for (Json::Value::ArrayIndex i = 0; i < source.size(); i++) + { + pugi::xml_node node = target.append_child(); + node.set_name(arrayElement.c_str()); + JsonToXmlInternal(node, source[i], arrayElement); + } + break; + } + + case Json::objectValue: + { + Json::Value::Members members = source.getMemberNames(); + + for (size_t i = 0; i < members.size(); i++) + { + pugi::xml_node node = target.append_child(); + node.set_name(members[i].c_str()); + JsonToXmlInternal(node, source[members[i]], arrayElement); + } + + break; + } + + default: + throw OrthancException(ErrorCode_NotImplemented); + } + } + + + void Toolbox::JsonToXml(std::string& target, + const Json::Value& source, + const std::string& rootElement, + const std::string& arrayElement) + { + pugi::xml_document doc; + + pugi::xml_node n = doc.append_child(rootElement.c_str()); + JsonToXmlInternal(n, source, arrayElement); + + pugi::xml_node decl = doc.prepend_child(pugi::node_declaration); + decl.append_attribute("version").set_value("1.0"); + decl.append_attribute("encoding").set_value("utf-8"); + + ChunkedBufferWriter writer; + doc.save(writer, " ", pugi::format_default, pugi::encoding_utf8); + writer.Flatten(target); + } + +#endif } diff -r 6d90e2bcab60 -r 0bfeeb6d340f Core/Toolbox.h --- a/Core/Toolbox.h Thu Jul 17 16:01:41 2014 +0200 +++ b/Core/Toolbox.h Fri Jul 18 16:41:10 2014 +0200 @@ -37,6 +37,7 @@ #include #include #include +#include namespace Orthanc { @@ -136,5 +137,12 @@ void CreateDirectory(const std::string& path); bool IsExistingFile(const std::string& path); + +#if ORTHANC_PUGIXML_ENABLED == 1 + void JsonToXml(std::string& target, + const Json::Value& source, + const std::string& rootElement = "root", + const std::string& arrayElement = "item"); +#endif } } diff -r 6d90e2bcab60 -r 0bfeeb6d340f Resources/CMake/PugixmlConfiguration.cmake --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/PugixmlConfiguration.cmake Fri Jul 18 16:41:10 2014 +0200 @@ -0,0 +1,35 @@ +if (USE_PUGIXML) + add_definitions(-DORTHANC_PUGIXML_ENABLED=1) + + if (STATIC_BUILD OR NOT USE_SYSTEM_PUGIXML) + set(PUGIXML_SOURCES_DIR ${CMAKE_BINARY_DIR}/pugixml-1.4) + + DownloadPackage( + "7c56c91cfe3ecdee248a8e4892ef5781" + "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/pugixml-1.4.tar.gz" + "${PUGIXML_SOURCES_DIR}") + + include_directories( + ${PUGIXML_SOURCES_DIR}/src + ) + + set(PUGIXML_SOURCES + ${PUGIXML_SOURCES_DIR}/src/vlog_is_on.cc + ) + + list(APPEND THIRD_PARTY_SOURCES + ${PUGIXML_SOURCES_DIR}/src/pugixml.cpp + ) + + else() + CHECK_INCLUDE_FILE_CXX(pugixml.h HAVE_PUGIXML_H) + if (NOT HAVE_PUGIXML_H) + message(FATAL_ERROR "Please install the libpugixml-dev package") + endif() + + link_libraries(pugixml) + endif() + +else() + add_definitions(-DORTHANC_PUGIXML_ENABLED=0) +endif() diff -r 6d90e2bcab60 -r 0bfeeb6d340f UnitTestsSources/UnitTestsMain.cpp --- a/UnitTestsSources/UnitTestsMain.cpp Thu Jul 17 16:01:41 2014 +0200 +++ b/UnitTestsSources/UnitTestsMain.cpp Fri Jul 18 16:41:10 2014 +0200 @@ -674,6 +674,25 @@ } +#if ORTHANC_PUGIXML_ENABLED == 1 +TEST(Toolbox, Xml) +{ + Json::Value a; + a["hello"] = "world"; + a["42"] = 43; + a["b"] = Json::arrayValue; + a["b"].append("test"); + a["b"].append("test2"); + + std::string s; + Toolbox::JsonToXml(s, a); + + std::cout << s; +} + +#endif + + int main(int argc, char **argv) { // Initialize Google's logging library.