2 Kasım 2017 Perşembe

property_tree xml

property_tree Sınıfı
Giriş
property_tree sınıfı için şu satırı dahil ederiz.
#include <boost/property_tree/ptree.hpp>
Xml işlemleri için şu satırı dahil ederiz. Sadece bu satırı dahil etmek yeterli.
#include <boost/property_tree/xml_parser.hpp>
Constructor
Şöyle yaparız.
using boost::property_tree::iptree;
iptree pt;
add metodu - attribute ekler
Şöyle yaparız.
struct { int id, age; std::string value; } data[] = {
        { 12, 7, "123" },
        { 15, 8, "1rr" },
        { 52, 71, "1qe3" },
        { 72, 5, "1d5" },
    };

ptree tests;

for (auto& item : data) {
  ptree test;
  test.add("<xmlattr>.id", item.id);
  test.add("<xmlattr>.age", item.age);
  test.put_value(item.value);
  tests.add_child("test", test);
};

boost::property_tree::ptree pt;
pt.add_child("tests", tests);
write_xml(std::cout, pt,
  boost::property_tree::xml_writer_make_settings<std::string>(' ', 4));
Çıktı olarak şunu alırız.
<?xml version="1.0" encoding="utf-8"?>
<tests>
    <test id="12" age="7">123</test>
    <test id="15" age="8">1rr</test>
    <test id="52" age="71">1qe3</test>
    <test id="72" age="5">1d5</test>
</tests>
add metodu - düğüm ekler
Yeni düğüm ekler. add_child ile aynıdır. Farklı olarak add_child ikinci parametre olarak property_tree alırken add() metodu XML string'lerini alır.
Örnek
Elimizde bir xml olsun
<MyXML>
    <Tag2>2</Tag2>
    <Tag3>3</Tag2>
    <Tag4>4</Tag3>
</MyXML>
En sona yeni bir düğüm eklemek için şöyle yaparız.
xmlroot.add("MyXML.Tag5", "5");
Çıktı olarak şunu alırız
<MyXML>
    <Tag2>2</Tag2>
    <Tag3>3</Tag2>
    <Tag4>4</Tag3>
    <Tag5>5</Tag5>
</MyXML>
Örnek
Şöyle yaparız.
ptree root;
root.add("Txn.Resp.<xmlattr>.errCode", 0);
root.add("Txn.Resp.<xmlattr>.errInfo", "");

root.add("Txn.A", "xyz Information");
root.add("Txn.A.<xmlattr>.exptime", "20171230");

root.add("Txn.B", "xyz Information");

root.add("Txn.C", "xyz Information");
root.add("Txn.C.<xmlattr>.type", "Active");

write_xml(std::cout, root, pretty);
Çıktı olarak şunu alırız
<?xml version="1.0"?>
<Txn>
  <Resp errCode="0" errInfo="" />
  <A exptime="20171230">xyz Information</A>
  <B>xyz Information</B>
  <C type="Active">xyz Information</C>
</Txn>
add_child metodu - property_tree
Yeni bir düğüm ekler.
Örnek 
Şöyle yaparız.
// Create the first tree with two elements, name and contents
boost::property_tree::ptree ptr1;
ptr1.put("name", "a2");
ptr1.put("contents", "adsf");

// Create the a second tree with two elements, name and contents
boost::property_tree::ptree ptr2;
ptr2.put("name", "d6");
ptr2.put("contents", "345");

// Add both trees to a third and place them in node "spreadsheet.cell"
boost::property_tree::ptree ptr3;
ptr3.add_child("spreadsheet.cell", ptr1);
ptr3.add_child("spreadsheet.cell", ptr2);

boost::property_tree::write_xml("output.xml", ptr3);
Çıktı olarak şunu alırız.
<?xml version="1.0" encoding="utf-8"?>
<spreadsheet>
  <cell>
    <name>a2</name>
    <contents>adsf</contents>
  </cell>
  <cell>
    <name>d6</name>
    <contents>345</contents>
  </cell>
</spreadsheet>
Örnek
root'a list ve asset list düğümlerini eklemek için şöyle yaparız.
ptree pt;
auto& root = pt.add_child("root", ptree{});
auto& list = root.add_child("list", ptree{});
auto& assetlist = root.add_child("assetlist", ptree{});
Çıktı olarak şunu alırız.
<?xml version="1.0" encoding="utf-8"?>
<root>
  <list>
    ...
  </list>
  <assetlist>
    ...
  </assetlist>
</root>
erase metodu
İsmi verilen düğümü siler.
Örnek
Şöyle yaparız.
boost::property_tree::ptree pt;
...
pt.erase("tagname");
Örnek
Elimizde şöyle bir XML olsun
<BookData>
  <Book><Author>A1<Author><Name>B1</Name><Price>C1</Price></Book>
  <Book><Author>A2<Author><Name>B2</Name><Price>C2</Price></Book>
  ...
  <Book><Author>A(n-1)<Author><Name>B(n-1)</Name><Price>C(n-1)</Price></Book>
  <Book><Author>A(n)<Author><Name>B(n)</Name><Price>C(n)</Price></Book> 
</BookData>
En son düğümü yani A(n) düğümünü silmek için şöyle yaparız.
boost::property_tree::ptree pt = ...;

auto& root = pt.get_child("BookData");
root.erase(std::next(root.rbegin()).base());
Çıktı olarak şunu alırız.
<BookData>
  <Book><Author>A1<Author><Name>B1</Name><Price>C1</Price></Book>
  <Book><Author>A2<Author><Name>B2</Name><Price>C2</Price></Book>
  ...
  <Book><Author>A(n-1)<Author><Name>B(n-1)</Name><Price>C(n-1)</Price></Book> 
</BookData>
Örnek
Elimizde şöyle bir XML olsun
<root>
  <stu id="1">
    <name>a</name>
  </stu>
  <stu id="2">
    <name>b</name>
  </stu>
  <stu id="3">
    <name>c</name>
  </stu>
</root>
Şöyle yaparız.
template <typename Tree>
auto find_children(Tree& pt, std::string const& key) {
  std::vector<typename Tree::iterator> matches;

  for (auto it = pt.begin(); it != pt.end(); ++it)
    if (it->first == key)
      matches.push_back(it);

  return matches;
}

ptree pt = ...;

auto& root = pt.get_child("root");

for (auto stu : find_children(root, "stu")) {
  if (2 == stu->second.get("<xmlattr>.id", -1)) {
    root.erase(stu);
  }
}
Çıktı olarak şunu alırız.
<?xml version="1.0" encoding="utf-8"?>
<root>
  <stu id="1">
    <name>a</name>
  </stu>
  <stu id="3">
    <name>c</name>
  </stu>
</root>
get_child metodu
xml Parse Etme yazısına taşıdım.

get metodu
xml Parse Etme yazısına taşıdım.

get_value metodu - tag içindeki değer
xml Parse Etme yazısına taşıdım.

push_front metodu - ptree
add_child() metodu gibi yaratılış bir ptree nesnesini en öne ekler. Elimizde bir xml olsun. En öne yeni bir düğüm eklemek isteyelim. Şöyle yaparız.
pt::ptree tree = ...;
auto root = tree.find("MyXML");
root->second.push_front({"NewTag", decltype(tree)("1")});
put metodu - Düğüm yaratır
Şöyle yaparız.
pt.put("tagname",newval);
put_value metodu - tag içindeki değer
Tag'in value değerini değiştirir. Elimizde şöyle bir xml olsun. value değerini cenc'den başka bir şeye değiştirmek isteyelim
<MPD>
  <Period>
    <AdaptationSet>
      <Cp schemeIdUri="1" value="cenc"/>
      <ContentProtection schemeIdUri="...">
    </AdaptationSet>
  </Period>
</MPD>
Şöyle yaparız.
for (auto& as : pt.get_child("MPD.Period")) {
  if (as.first == "AdaptationSet") {
    for (auto& cp : as.second) {
      if (cp.first == "Cp" && cp.second.get("<xmlattr>.schemeIdUri", "") == "1"){
        cp.second.put_value("NEW VALUE");
      }
    }
  }
}
Diğer
Sınıfın alt düğümlerini dolaşmak için şöyle yaparız.
Tree pt = ...;
for (auto& child : pt) {
  if (child.first == "Foo") {     Do something with child.second;
  }       
}
XPath
Ptree parent düğümü bilmez ve erişmek için bir metod sağlamaz. Bu yüzden hep yukarıdan başlayarak gelmek gerekir. Açıklaması şöyle
Boost Ptree nodes are self-contained and do not know about any containing datastructure (it's the the "tree" equivalent of a singly-linked list).
XPath yeteneğini sunmaz, ancak şöyle yaparız.
template <typename Tree, typename Out>
Out enumerate_nodes(Tree const& pt, typename Tree::path_type path, Out out) {
  if (path.empty())
    return out;

  if (path.single()) {
    auto name = path.reduce();
    for (auto& child : pt)
    {
      if (child.first == name)
        *out++ = child.second;
      }
  } else {
    auto head = path.reduce();
    for (auto& child : pt) {
      if (head == "*" || child.first == head) {
        out = enumerate_nodes(child.second, path, out);
      }
    }
  }

  return out;
}
Şöyle yaparız.
std::vector<std::reference_wrapper<ptree const> > flights;
enumerate_nodes<ptree>(pt, "arrayOfSked.sked.flight", back_inserter(flights));
property_tree::path_type Sınıfı
empty metodu
Şöyle yaparız.
ptree::path_type path = "arrayOfSked.sked.flight";
if (path.empty()) {...}
reduce metodu
Noktadan önceki ilk kısmı döner. Şöyle yaparız.
ptree::path_type path = "arrayOfSked.sked.flight";
auto head = path.reduce();
En son kısmı almak için şöyle yaparız.
ptree::path_type const nodepath = "config.lambda";

auto nodename = [nodepath] {
  auto copy = nodepath;
  while (!copy.single())
    copy.reduce();
  return copy.reduce();
}();
single metodu
Arada nokta olup olmadığını döner. Şöyle yaparız.
ptree::path_type path = "arrayOfSked.sked.flight";
if (path.single()) {...}
xml_writer_settings Sınıfı
Giriş
Bu sınıfın açıklaması şöyle. Varsayılan ayarları kullanmamak gerekir.
//! Xml writer settings. The default settings lead to no pretty printing.
template<class Str>
class xml_writer_settings
{...}
constructor
Şöyle yaparız.
auto xws = boost::property_tree::xml_writer_make_settings<char>('\t', 4);
Şöyle yaparız.
auto xws = boost::property_tree::xml_writer_make_settings<std::string>(' ', 4);
Free Style Metodlar
read_xml metodu - istream
Kullanılan yığıt boyutunu ayarlamak için şöyle yaparız.
#define BOOST_PROPERTY_TREE_RAPIDXML_STATIC_POOL_SIZE 512
Şöyle yaparız.
std::string const sample = R"...";
using boost::property_tree::iptree;
iptree pt;
std::istringstream iss (sample);
read_xml(iss, pt);
read_xml metodu - wifstream
portable kod değil ama şöyle yaparız.
boost::property_tree::wptree pt;
std::wifstream f(L"C:/äöå/file.xml");
boost::property_tree::read_xml(f, pt);
read_xml metodu - boost::iostreams::stream
Şöyle yaparız
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);
write_xml metodu
write_xml metodu yazısına taşıdım.

Hiç yorum yok:

Yorum Gönder