我想解析使用以下模式的XML文件,并在“adif”和“name”这两个元素中提取数据并将它们放在Dictionary中。 我真的不知道如何使用任何内置的.net类或HTML Agility Pack来解决这个问题。
有人可以向我发送正确的方向吗? 感谢
<?xml version="1.0" encoding="utf-16"?>
<xs:schema xmlns="http://www.clublog.org/cty/v1.0" attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.clublog.org/cty/v1.1" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="clublog">
<xs:complexType>
<xs:sequence>
<xs:element name="entities">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="unbounded" name="entity">
<xs:complexType>
<xs:sequence>
<xs:element name="adif" type="xs:decimal" />
<xs:element name="name" type="xs:string" />
<xs:element name="prefix" type="xs:string" />
<xs:element name="deleted" type="xs:boolean" />
<xs:element name="cqz" type="xs:unsignedByte" />
<xs:element name="cont" type="xs:string" />
<xs:element name="long" type="xs:decimal" />
<xs:element name="lat" type="xs:decimal" />
<xs:element minOccurs="0" name="start" type="xs:dateTime" />
<xs:element minOccurs="0" name="end" type="xs:dateTime" />
<xs:element minOccurs="0" name="whitelist" type="xs:boolean" />
<xs:element minOccurs="0" name="whitelist_start" type="xs:dateTime" />
<xs:element minOccurs="0" name="whitelist_end" type="xs:dateTime" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="exceptions">
<xs:complexType>
我对实体节点以外的任何其他内容都不感兴趣。其中最多约有400个,而例外情况则是数千个。 我到目前为止的代码是
using (WebClient wc = new WebClient())
{
wc.DownloadFile("https://secure.clublog.org/cty.php?api="API","Test.gz");
var doc = new HtmlAgilityPack.HtmlDocument();
using (var file = File.Open("Test.gz", FileMode.Open))
using (var zip = new GZipStream(file, CompressionMode.Decompress))
{
doc.Load(zip);
}
Dictionary<string, string> dict = new Dictionary<string, string>();
就是这样。当然,HTML Agility包没有文档,我对解析XML代码的理解是有限的。
这就是我所在的地方: XD包含有效的xml数据。
private void button1_Click(object sender, EventArgs e)
{
var dict = (Dictionary<string, decimal>)null;
using (WebClient wc = new WebClient())
{
wc.DownloadFile("https://secure.clublog.org/cty.php?api=", "Test.gz");
using (var file = File.Open("Test.gz", FileMode.Open))
{
using (var zip = new GZipStream(file, CompressionMode.Decompress))
{
using (var xmlReader = XmlReader.Create(zip))
{
// Dictionary<string, decimal> dict = new Dictionary<string, decimal>();
var xd = XDocument.Load(xmlReader);
}
这里是xml数据....两条记录。我试图将文件保存在我的服务器上,它不会让我......
<?xml version="1.0" encoding="utf-8" ?>
-<clublog xmlns="http://www.clublog.org/cty/v1.0" date="2014-03-16T08:30:03+00:00">
-<entities>
-<entity>
<adif>1</adif>
<name>CANADA</name>
<prefix>VE</prefix>
<deleted>FALSE</deleted>
<cqz>5</cqz>
<cont>NA</cont>
<long>-80.00</long>
<lat>45.00</lat>
</entity>
-<entity>
<adif>2</adif>
<name>ABU AIL IS</name>
<prefix>A1</prefix>
<deleted>TRUE</deleted>
<cqz>21</cqz>
<cont>AS</cont>
<long>45.00</long>
<lat>12.80</lat>
<end>1991-03-30T23:59:59+00:00</end>
答案 0 :(得分:0)
Jeenkies。我刚刚写了一个很好的答案来解决另一个问题。如果你可以使用.NET 3.5,你可以使用linq-to-xml,这将使这变得非常容易。
让我们开始吧。首先,您需要加载您的文档。查看here和here以获得一些帮助。我认为第二个会帮助你更多。
现在进行挖掘。由于您对可能只有几层深的节点感兴趣,因此这不应该太痛苦。在这一点上,我们遇到了2个设计(我能想到)逐层切割并将其爆破成小块。由于您处理的是相当大量的数据,因此切片可能会更快,但可能不会。所以我将包括两个设计,让你从那里进行测试。
此设计将假设doc
代表整个xml文档。
切削方法:
var elements = doc.Elements(xs:element).Where(el => el.Attribute("name").Value == "entities");
从那里开始使用Elements()
和Attributes()
的组合应该很简单。
爆破方法只是将Elements()
替换为Descendants()
。如果您正在处理近根级节点,我只是坚持使用切片方法。
现在将它放入Dictionary
。 This应该指出正确的方向。这肯定对我来说很方便。
答案 1 :(得分:0)
这样的事情对你有用:
var dict = (Dictionary<string, decimal>)null;
using (WebClient wc = new WebClient())
{
var text = wc.DownloadString(
"https://secure.clublog.org/cty.php?api=" + API);
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(text)))
{
using (var zip = new GZipStream(stream, CompressionMode.Decompress))
{
using (var xmlReader = XmlReader.Create(zip))
{
var xd = XDocument.ReadFrom(xmlReader);
dict =
xd
.Document
.Root
.Element(XName.Get("entities", "http://www.clublog.org/cty/v1.0"))
.Elements(XName.Get("entity", "http://www.clublog.org/cty/v1.0"))
.ToDictionary(
x => x.Element(XName.Get("name", "http://www.clublog.org/cty/v1.0")).Value,
x => (decimal)x.Element(XName.Get("adif", "http://www.clublog.org/cty/v1.0")));
}
}
}
}
我假设您确实想要Dictionary<string, decimal>
给定“adif”类型,但如果我错了,应该很容易改变。
我的方法避免了所有文件的混乱。