增强XML解析的复杂性-C#XML循环 [英] Enhance XML Parsing complexity - c# XML Looping
问题描述
我正在编写自己的c#自定义地图导航程序.我正在使用 OpenStreetMaps 作为地图数据.这是一个大型XML文件,其中包含节点和方式.我写了一个转换器,将XML文件从无用的垃圾中删除(例如时间戳,用户等),以使文件变小.
I am writing my own c# custom map navigation program. I am using OpenStreetMaps for the map data. It's a large XML file that contains Nodes and ways. I wrote a convertor that strips the XML file from useless junk (like timestamp, user etc) so the file will become smaller.
现在,当我尝试遍历XML并将数据转换为C#对象的方式和节点时,遇到了一个问题.我需要做很多循环,以至于加载时间太长.
Now while I attempt to loop through the XML and convert the data to C# object Ways and Nodes I came across a problem. I need to do so much looping that the loading time is way too long.
XML示例(w =方式,n =节点,rf =引用节点):
<n id="2638006578" l="5.9295547" b="52.5619519" />
<n id="2638006579" l="5.9301973" b="52.5619526" />
<n id="2638006581" l="5.9303625" b="52.5619565" />
<n id="2638006583" l="5.9389539" b="52.5619577" />
<n id="2638006589" l="5.9386643" b="52.5619733" />
<n id="2638006590" l="5.9296231" b="52.5619760" />
<n id="2638006595" l="5.9358987" b="52.5619864" />
<n id="2638006596" l="5.9335913" b="52.5619865" />
<w id="453071384">
<nd rf="2638006581" />
<nd rf="2638006590" />
<nd rf="2638006596" />
<nd rf="2638006583" />
<nd rf="2638006578" />
</w>
<w id="453071385">
<nd rf="2638006596" />
<nd rf="2638006578" />
<nd rf="2638006581" />
<nd rf="2638006583" />
</w>
-
方式"节点包含对节点的引用,因此一个节点可以多种方式存在(节点连接方式).
The Way nodes contain references to nodes, so a node can be existent in multiple ways (the nodes connect the ways).
节点包含经度和纬度(l = lon,b = lat).
nodes contain a longitude and latitude (l = lon, b = lat).
这些XML文件包含很多节点和方式,因此它不仅仅是一个小文件.下面的代码示例中的XML文件有50万行.
These XML files contain a lot of nodes and ways, so it's not just a small file. The XML file in the code example below has 500K lines.
我的代码
class Program { static List<Way> ways = new List<Way>(); static List<Node> nodes = new List<Node>(); static void Main(String[] args) { read(); } public static void read() { String xmlLoc = @"C:\Users\MyName\Desktop\result.xml"; long time = DateTime.Now.Ticks; Parse(xmlLoc); long time2 = DateTime.Now.Ticks; Console.WriteLine("Done: {0} ms", (time2 - time) / 10000); Console.WriteLine(" - Nodes Amount:" + nodes.Count()); Console.WriteLine(" - Ways Amount: " + ways.Count()); } private static Node GetByRef(long reference) { return nodes.First(x => x.ID == reference); } private static void Parse(string path) { using (XmlReader reader = XmlReader.Create(path)) { reader.MoveToContent(); while (reader.Read()) { if (reader.NodeType == XmlNodeType.Element) { XElement element = XElement.ReadFrom(reader) as XElement; if ( element.Name.ToString().Equals("w")) { Way w = new Way(); var name = element.Attribute("nm"); if (name != null) w.Name = name.Value; var children = element.Descendants("nd"); foreach (XElement child in children) w.References.Add(long.Parse(child.Attribute("rf").Value)); ways.Add(w); }else if (element.Name.ToString().Equals("n")) { Node n = new Node(); n.ID = long.Parse(element.Attribute("id").Value); n.Lon = double.Parse(element.Attribute("l").Value); n.Lat = double.Parse(element.Attribute("b").Value); nodes.Add(n); } } } } } } class Way { public List<long> References { get; private set; } public long ID { get; set; } public String Name { get; set; } public bool OneWay { get; set; } public Way() { this.References = new List<long>(); } } class Node { public long ID { get; set; } public double Lat { get; set; } public double Lon { get; set; } }
当前,类Way和Node之间没有实际关系.只有一个具有
long
值的列表.我不知何故需要在Way类中添加一个带有Nodes的列表,但这将需要我处理另一个(两个?)for/while循环.我相信那将意味着O(N4),这很慢.Currently there's no actual relation between the class Way and the class Node. There's only a list with
long
values. I somehow need to add a list with Nodes to the class Way, but that'll require me to work with another (two?) for/while loops. That would mean O(N4) I believe, which is slow.从技术上讲,我正在寻找一种解决方案和更好地构建此解决方案的方法,如果您有建议,我想听听它!
Technically I am looking for both a solution and ways to build this better, if you have advise I'd like to hear it!
提前谢谢!
PS::如果我应该更新/编辑问题,请告诉我,而不是立即投票.
PS: If I should update/edit my question, please tell me instead of downvoting immediately.
推荐答案
使用xml linq
Use xml linq
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Data; using System.Xml; using System.Xml.Linq; using System.IO; namespace ConsoleApplication31 { class Program { const string FILENAME = @"c:\temp\test.xml"; static void Main(string[] args) { XDocument xdoc = XDocument.Load(FILENAME); var results = xdoc.Elements("root").Select(x => new { ns = x.Descendants("n").Select(y => new { id = (long)y.Attribute("id"), l = (double)y.Attribute("l"), b = (double)y.Attribute("b") }).ToList(), ws = x.Descendants("w").Select(y => new { id = (long)y.Attribute("id"), rfs= y.Descendants("nd").Select(z => (long)z.Attribute("rf")).ToList() }).ToList() }).FirstOrDefault(); } } }
这篇关于增强XML解析的复杂性-C#XML循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!