分析 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
        }
    }
}

谢谢!

分析 XML 文档(格式异常)C#

假设您有一个架构或可以生成一个可靠的架构,则可以将对象序列化为 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();