About

地図会社で働いていたプログラマ。

2012年12月8日土曜日

C#とC++でXMLをパースするサンプルソース比較

パースするXML


<osm generator="CGImap 0.0.2" version="0.6">
 <bounds maxlat="34.6669570" maxlon="135.4578320" minlat="34.6642090" minlon="135.4537220">
  <node changeset="8937729" id="288188103" lat="34.6691643" lon="135.4618170" timestamp="2011-08-06T12:45:02Z" uid="151227" user="MaryHiroshige" version="5" visible="true">
  </node>
  <node changeset="894707" id="325609282" lat="34.6611820" lon="135.4492029" timestamp="2009-04-22T09:07:45Z" uid="35930" user="Show-ichi" version="2" visible="true">
   <tag k="created_by" v="Merkaartor 0.12"></tag>
  </node>
 </bounds>
</osm>

C#のソース

// Program.cs
using System;
using System.Diagnostics;

namespace yukinarit.osm
{
 class Program
 {
  static void Main(string[] args)
  {
   Stopwatch sw = new Stopwatch();
   sw.Start();

   try
   {
    // パーサークラス
    OsmParserosmParser = new OsmParser();
    // 読み込み
    OsmParser.Load(@"Osm\map.osm");

    // 読み込んだXMLから"yukinarit"の値をもつデータを検索する
    var node = osmParser.SearchNodeByUser("yukinarit");
    Console.WriteLine(node);
   }
   catch (Exception ex)
   {
    Console.WriteLine(ex.Message);
   }

   sw.Stop();
   Console.WriteLine("-----Program Ended-----\n");
   Console.WriteLine("Elapsed Time: {0}", sw.Elapsed);
   Console.ReadLine();
  }
 }
}

// OsmParser.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml;

namespace yukinarit.osm
{
 class OsmParser
 {
  public OsmParser()
  {
   xmlDoc = new XmlDocument();
   nodes  = new List<OsmNode>();
  }

  public void Load(string path)
  {
   xmlDoc.Load(path);

   foreach (var e in xmlDoc.DocumentElement.SelectNodes("node"))
   {
    XmlNode enode = e as XmlNode;
    if (enode == null)
     continue;

    OsmNode node = new OsmNode();
    node.id   = Convert.ToInt32(enode.Attributes["id"].Value);
    node.lat  = Convert.ToDouble(enode.Attributes["lat"].Value);
    node.lon  = Convert.ToDouble(enode.Attributes["lon"].Value);
    node.user = enode.Attributes["user"].Value;

    this.nodes.Add(node);
   }
  }

  public OsmNode SearchNodeByUser(string user)
  {
   var queryUser = from node in nodes
    where node.user.Equals(user)
    select node;

   return queryUser.ToList()[0];
  }

  private XmlDocument xmlDoc;
  private List<OsmNode> nodes;
 }
}

// OsmNode.cs
using System;
using System.Collections.Generic;

namespace yukinarit.osm
{
 class OsmNode
 {
  public int? id;
  public double? lat;
  public double? lon;
  public string user;
  public Dictionary<string, string> attr = new Dictionary<string,string>();

  public override string ToString()
  {
   return String.Format("<node id={0} lat={1} lon={2} user={3} />",
    id, lat, lon, user);
  }
 }
}

C++のソース

// ParceOsm.cpp
#include "stdafx.h"
#include "OsmParser.h"

int _tmain(int argc, wchar_t* argv[])
{
 using namespace std;
 using namespace yukinarit::osm;

 time_t start = clock();

 try
 {
  // パーサークラス
  OsmParser osmParser;
  // 読み込み
  osmParser.Load("Osm\\map.osm");

  // 読み込んだXMLから"yukinarit"の値をもつデータを検索する
  auto node = osmParser.SearchNodeByUser("yukinarit");
  cout << node.ToString() << endl;;
 }
 catch (const std::exception &ex)
 {
  cout << ex.what() << endl;
 }

 time_t end = clock();
 cout << "-----Program Ended-----\n";
 cout << "Elapsed Time: " << (end - start) << endl;
 cin.get();
 return 0;
}

// stdafx.h
#pragma once
#include "targetver.h"
#include <tchar.h>
#include <time.h>

#include <iostream>
#include <vector>
#include <unordered_map>
#include <sstream>
#include <algorithm>
#include <boost/property_tree/xml_parser.hpp>

// OsmParser.h
#pragma once
#include "stdafx.h"
#include "IParser.h"
#include "OsmNode.h"

namespace yukinarit
{
 namespace osm
 {

  class OsmParser
  {
  public:
   OsmParser() {};
   virtual ~OsmParser() {};

   virtual void Load(const std::string &path) override
   {
    using namespace boost::property_tree::xml_parser;
    using boost::property_tree::ptree;

    boost::property_tree::xml_parser::read_xml(path, pt, 0, std::locale("japanese"));

    ptree &osm = pt.get_child("osm");
    for (auto e = osm.begin(), end = osm.end(); e != end; e++)
    {
     if ((*e).first != "node")
      continue;

     OsmNode oNode;
     oNode.id =   (*e).second.get<int>("<xmlattr>.id");
     oNode.lat =  (*e).second.get<double>("<xmlattr>.lat");
     oNode.lon =  (*e).second.get<double>("<xmlattr>.lon");
     oNode.user = (*e).second.get<std::string>("<xmlattr>.user");

     nodes.push_back(oNode);
    }
   };

   virtual OsmNode SearchNodeByUser(const std::string &user)
   {
    using namespace std;

    auto found = find_if(nodes.begin(), nodes.end(), [&](const OsmNode &n) {
     return (n.user == user);
    });

    if (found != nodes.end())
     return *found;

    return OsmNode();
   };

  private:
   boost::property_tree::ptree pt;
   std::vector<OsmNode> nodes;
  };

 }
}

// OsmNode.h
#pragma once
#include "stdafx.h"

namespace yukinarit
{
 namespace osm
 {
  class OsmNode
  {
  public:
   OsmNode() : id(0),
   lat(0.0),
   lon(0.0),
   user(""),
   attr() {};
   virtual ~OsmNode() {};

   virtual std::string ToString()
   {
    std::stringstream s;
    s << "<node id=" << id << " lat=" << lat << " user=" << user << " />";
    return s.str();
   };

   int id;
   double lat;
   double lon;
   std::string user;
   std::unordered_map<std::wstring, std::wstring> attr;
  };

 }
}

0 Kommentarer:

コメントを投稿