分析 XML 文档(格式异常)C#
本文关键字:异常 格式 XML 文档 分析 | 更新日期: 2023-09-27 18:36:23
解析这个不寻常的xml文档的最佳方法是什么?
xml的一部分:
<?xml version="1.0" encoding="UTF-8"?>
<dataset xmlns="http://developer.cognos.com/schemas/xmldata/1/"
xmlns:xs="http://www.w3.org/2001/XMLSchema-instance">
<metadata>
<item name="AsOfDate" type="xs:string" length="12"/>
<item name="RateOfReturn" type="xs:double"/>
<item name="FamAcctIndex" type="xs:string" length="3"/>
<item name="RowID" type="xs:string" length="1"/>
<item name="BrM" type="xs:string" length="1"/>
<item name="ProductLineCode" type="xs:int"/>
</metadata>
<data>
<row>
<value>Apr 26, 2002</value>
<value>0.210066429</value>
<value>JA1</value>
<value>F</value>
<value>B</value>
<value>1</value>
</row>
<row>
<value>Apr 27, 2002</value>
<value>0.1111111</value>
<value>BBB</value>
<value>G</value>
<value>B</value>
<value>2</value>
</row>
</data>
</dataset>
当我说不寻常的xml文档时,我的意思是我从来没有用数据/行解析过某些东西。这是我通常会看到的:
<person gender="female">
<firstname>Anna</firstname>
<lastname>Smith</lastname>
</person>
我打算使用:
var xmlDoc = new XmlDocument();
xmlDoc.Load(stream);
//parse here
但是我想在开始之前我想知道最好的方法,因为它是一个非常大的文档。
编辑:
这是最好的方法吗?
var xml = XElement.Load(@"C:'Users'nunya'Desktop'example.xml").Element(XName.Get("data", "http://developer.cognos.com/schemas/xmldata/1/"));
var row = XName.Get("row", "http://developer.cognos.com/schemas/xmldata/1/");
var value = XName.Get("value", "http://developer.cognos.com/schemas/xmldata/1/");
if (xml != null)
{
foreach (var rowElement in xml.Elements(row))
{
foreach (var valueElement in rowElement.Elements(value))
{
//valueElement.Value is what i need
}
}
}
谢谢!
假设您有一个架构或可以生成一个可靠的架构,则可以将对象序列化为 C# 类,但这仍然使操作它变得复杂。 我将创建一个具有与标头值匹配的属性的类。 您可以尝试在该类的父类上实现IXmlSerializable
,但我认为编写使用 XDocument
返回列表的东西会更直接。
基本问题是弄清楚如何将列索引与行值索引对齐。 我使用字典和列表做到了这一点:
public class Product
{
public string AsOfDate { get; set; }
public double RateOfReturn { get; set; }
public string FamAcctIndex { get; set; }
public string RowID { get; set; }
public string BrM { get; set; }
public int ProductLineCode { get; set; }
}
public static IEnumerable<Product> ParseDataset(XDocument xd)
{
XNamespace ns = "http://developer.cognos.com/schemas/xmldata/1/";
// parse out the column names
Dictionary<string, int> headerPositions = xd.Root
.Element(ns + "metadata")
.Elements()
.Select((name, idx) => new { pos = idx, name = (string)name.Attribute("name") })
.ToDictionary(x => x.name, x => x.pos);
foreach (XElement row in xd.Root.Descendants(ns + "row"))
{
List<string> vals = row.Elements().Select(x => x.Value).ToList();
Product obj = new Product();
foreach (PropertyInfo prop in typeof(Product).GetProperties())
{
string valToSet = vals[headerPositions[prop.Name]];
prop.SetValue(obj, Convert.ChangeType(valToSet, prop.PropertyType);
}
yield return obj;
}
}
如果性能是一个问题,您可能希望避免使用反射,而只对属性名称使用 if/switch。 你可以像这样调用函数
XDocument xd = XDocument.Load(...);
List<Product> products = ParseDataset(xd).ToList();