C++ header-only converter from Json to XML, based in also header-only nlohmann json library.
Restrictions
- All future xml attributes, <u>**are expected to be prefixed**</u>. By default '@' is used (you can change it at
JsonSaxConsumer
constructor), like python xmltodict project does.
- XML text is not supported, so for example key nodes "#text" (default used by xmltodict) is not managed and hence fails as not prefixed like commented above.
- XML namespaces are also not expected, and user must expand equivalent top nodes to represent the scope desired.
In summary, this converter is intended to be used for simple xml configurations with predictable and controlled content:
{
"grandfather": {
"father": {
"child": [
{
"@name": "Jose",
"@bestFriend": "Maria"
},
{
"@name": "Maria",
"@bestFriend": "Jose"
}
],
"student": {
"@favoriteBook": "The Gods Themselves",
"@age": "21"
}
}
}
}
turns into:
<grandfather>
<father>
<child name="Jose" bestFriend="Maria"/>
<child name="Maria" bestFriend="Jose"/>
<student favoriteBook="The Gods Themselves" age="21"/>
</father>
</grandfather>
Integration
json2xml.hpp
is the single required file in include/ert
or released here. You need to add
#include <ert/json2xml.hpp>
You must also integrate nlohmann/json
header-only file (json.hpp) in your project.
CMake
Embedded
To embed the library directly into an existing CMake project, place the entire source tree in a subdirectory and call add_subdirectory()
in your CMakeLists.txt
file:
# Typically you don't care so much for a third party library's examples to be
# run from your own project's code.
set(ERT_JSON2XML_BuildExamples OFF CACHE INTERNAL "")
add_subdirectory(ert_json2xml)
...
add_library(foo ...)
...
target_link_libraries(foo PRIVATE ert_json2xml::ert_json2xml)
Embedded (FetchContent)
Since CMake v3.11, FetchContent can be used to automatically download the repository as a dependency at configure type.
Example:
include(FetchContent)
FetchContent_Declare(ert_json2xml
GIT_REPOSITORY https://github.com/testillano/json2xml.git
GIT_TAG v1.0.1)
FetchContent_GetProperties(ert_json2xml)
if(NOT ert_json_POPULATED)
FetchContent_Populate(ert_json2xml)
add_subdirectory(${ert_json2xml_SOURCE_DIR} ${ert_json2xml_BINARY_DIR} EXCLUDE_FROM_ALL)
endif()
target_link_libraries(foo PRIVATE ert_json2xml::ert_json2xml)
Build example and test natively
Build
Component test
CICD is tested with Codefresh. For local component test, on ubuntu you will need python3, pip3 and pytest & xmltodict modules:
$> apt-get update && apt-get install -y python3 python3-pip
$> pip3 install pytest xmltodict
Then, you shall change directory to ct
and just execute pytest
:
Don't forget to build the project first !
Execute example
A converter example based in the library header is located at example
directory:
$> examples/json2xml
$> Usage: json2xml <json file>
There are also some test files (test.<n>.json
) to play with:
Passing file
$> examples/json2xml examples/test.json | tee -a text.xml
This will output the xml representation, or an error.
Reverse check
You could do the opposite (xml to json) using python xmltodict
module:
$> python3 util/xml2json.py test.xml
You can also use this beautify perl script for json output, courtesy of yanOnGithub:
$> python3.9 util/xml2json.py test.xml | perl util/beautifyJson.perl
Build and test with docker
Build
You may remove cmake
cache from native workflow described above:
$> find . -name CMakeCache.txt -exec rm {} \;
Or perhaps you could execute:
Now, you will build the compilation docker image, and then build:
$> docker build -f dev/Dockerfile . -t dev_image:latest
$> docker run --rm -v $PWD:/code -w /code dev_image:latest bash -c "cmake . && make"
Component test
$> docker build -f ct/Dockerfile . -t ct_image:latest
$> docker run --rm -v $PWD:/code -w /code/ct ct_image:latest
Contributing
Please, execute astyle
formatting (using frankwolf image) before any pull request:
$> sources=$(find . -name "*.hpp" -o -name "*.cpp")
$> docker run -it --rm -v $PWD:/data frankwolf/astyle ${sources}