3

I recently started using std::wstring instead of std::string to avoid weird results with non-ASCII characters, and I didn't find a way to read an XML file where the path is of type std::wstring using the boost library.

I'm using the boost library quiet a lot nowadays.

I use the boost::property_tree::read_xml function with boost::property_tree::wptree instead of the usual ptree struct. But sadly I cannot feed a std::wstring as the first parameter to read_xml which makes it all harder.

My question is, are there any work around for reading a XML file where the path is storted as a std::wstring?

Thanks in advance!

Linus
  • 1,516
  • 17
  • 35

2 Answers2

4

You could use the Boost Iostreams file_descriptor_sink device which supports wpath from Boost Filesystem:

#include <boost/property_tree/xml_parser.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/filesystem.hpp>
#include <iostream>

namespace pt = boost::property_tree;
namespace io = boost::iostreams;
namespace fs = boost::filesystem;

int main()
{
    fs::wpath const fname = L"test.xml";
    io::file_descriptor_source fs(fname);
    io::stream<io::file_descriptor_source> fsstream(fs);

    pt::ptree xml;
    pt::read_xml(fsstream, xml);

    for (auto const& node : xml.get_child("root"))
        std::cout << node.first << ": " << node.second.get_value<std::string>() << "\n";
}

See it Live On Coliru where it uses the input file:

<root>
    <child nodetype="element" with="attributes">monkey show</child>
    <child nodetype="element">monkey do</child>
</root>

and prints:

child: monkey show
child: monkey do
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Does this work if my filename or path contains non ascii characters? – ashish g Jan 29 '15 at 14:49
  • @ashishg I haven't tested this, but I think `boost::filesystem::path::codecvt()` performs the relevant conversion so: yes – sehe Jan 29 '15 at 14:50
  • http://coliru.stacked-crooked.com/a/7007dd21b1c12f14 I tried modifying your example to include a non ascii and it errored out. – ashish g Jan 29 '15 at 15:04
  • 1
    @ashishg works for me. Anyhoops, imbueing a specific locale *[does the job on Coliru](http://coliru.stacked-crooked.com/a/393e7bd6069b3ce5) – sehe Jan 29 '15 at 16:13
0

I found a working solution which was rather simple, all I did was use the std::wifstream as the first parameter of the boost::property_tree::read_xml method.

Basically three lines of code:

boost::property_tree::wptree pt;
std::wifstream f(L"C:/äöå/file.xml");
boost::property_tree::read_xml(f, pt);
Linus
  • 1,516
  • 17
  • 35
  • 1
    That's not portable: http://en.cppreference.com/w/cpp/io/basic_ifstream/basic_ifstream - this is also the reason that `boost::iostreams::file_source` **[doesn't support wide string filenames](https://svn.boost.org/trac/boost/ticket/3088)** (because it relies on `std::fstream`) - that boost issue #3088 is marked "WontFix" for this very reason. – sehe Aug 29 '14 at 22:02
  • @sehe Okay, but it does work on Microsoft windows? Because my application is not (yet) made cross-platform. Anyway thank you for the information and the answer. – Linus Aug 29 '14 at 22:03
  • Cheers. I assume it just works with MSVC's standard library implementation. (It will still not work with MingW, GCC, Clang or Intel C++ compiler on windows). It's not the first thing that MSVC has non-standard. In general, wstring is rarely used outside Windows, because only on MSVC does wstring have 16-bit char types and that happens to coincide with the Windows "preferred" character encoding of UTF16 – sehe Aug 29 '14 at 22:06
  • @sehe I see, well would there be any benefit to use your method if developing on windows and in Visual Studio? Vcredist is going to be installed on all the computers running my program. – Linus Aug 29 '14 at 22:09
  • I bet no. You can use the MSVC extension if that's all you wish to support. ([docs](http://msdn.microsoft.com/en-us/library/zek0beca.aspx)) – sehe Aug 29 '14 at 22:12
  • @sehe Okay, but the example was nice, though. I can't use wptree using the boost stream, but that is not necessary unless the XML file contains non-ASCII characters? – Linus Aug 29 '14 at 22:16