簡體   English   中英

C#通用XML閱讀器代碼

[英]C# Generic XML reader code

我有一個程序,該程序解析三個不同的CrystalReport XML文件(結構相似,但后代級別不同),然后將值填充到一個類中。

這是第一個示例:

    public static List<VyplatnePasky> DeserialzieRozuctovanieMzdy(ref List<VyplatnePasky> _pasky, string sPath)
    {
        XDocument document = XDocument.Load(sPath);
        var formattedAreaPairReport = from d in document.Descendants("FormattedReport".AddNamespace())
                                                        .Descendants("FormattedAreaPair".AddNamespace())
                                                        .Descendants("FormattedAreaPair".AddNamespace())
                                      select d.Element("FormattedAreaPair".AddNamespace());

        if (formattedAreaPairReport.Count() == 0)
        {
            //empty;
            InsertErrorMessage("<formattedAreaPairReport> contains no data! No Data to parse from.", "DeserialzieRozuctovanieMzdy");
            return _pasky;
        }

        //check if any sequence contains any matching elements
        var GotElements = formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()).Where(n=>n.Attribute("Level").Value == "3" && n.Attribute("Type").Value == "Group");
        if (GotElements == null)
        {
            InsertErrorMessage("There are no matching elements under <formattedAreaPairReport>.", "DeserialzieRozuctovanieMzdy");
            return _pasky;
        }

        foreach (XElement xElement in GotElements)
        {
            RozuctovanieMzda_Values(xElement, ref _pasky);
        }

        return _pasky;
    }

這是第二個(第二個XML文檔解析器):

    public static List<VyplatnePasky> DeserializeVyplatnePasky(string sPath)
    {
        List<VyplatnePasky> _pasky = new List<VyplatnePasky>();

        XDocument document = XDocument.Load(sPath);
        var formattedAreaPairReport = from d in document.Descendants("FormattedReport".AddNamespace())
                                      select d.Element("FormattedAreaPair".AddNamespace());

        if (formattedAreaPairReport.Count() == 0)
        {
            //empty;
            InsertErrorMessage("<formattedAreaPairReport> contains no data! No Data to parse from.", "DeserializeVyplatnePasky");
        }
        else
        {
            //sequence contains data
            foreach (XElement xElement in formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()))
            {
                VyplatnePasky _paska = new VyplatnePasky();
                VyplatnePasky_Items(xElement, ref _paska);

                _pasky.Add(_paska);
            }
        }
        return _pasky;
    }

從上面的代碼中可以看到,所有三種XML解析方法看起來幾乎都相同。 主要區別在於我在諸如formattedAreaPairReport下的子孫中走了多深

我想做的是通過創建可以被這三種方法使用的通用void,使此代碼更加專業和可重用。

我當時正在考慮創建多個代表,然后在其中傳遞我的lambda命令,例如:

            var formattedAreaPairReport = ProcessFirstLevel(from d in document.Descendants("FormattedReport".AddNamespace())
                                      select d.Element("FormattedAreaPair".AddNamespace()));

但是它將變成一個大的混亂空間。

問題是-這實際上可行/值得嗎? 你能幫忙嗎?

您可以使用一些簡潔的編碼技術來使代碼干燥一些。 嘗試做這樣的事情:

public static List<VyplatnePasky> DeserialzieRozuctovanieMzdy(ref List<VyplatnePasky> _pasky, string sPath)
{
    var formattedAreaPairReport =
    tryToGetItemsFromDocument
    (
        sPath,
        document=>from d in document.Descendants("FormattedReport".AddNamespace())
                  .Descendants("FormattedAreaPair".AddNamespace())
                  .Descendants("FormattedAreaPair".AddNamespace())
                  select d.Element("FormattedAreaPair".AddNamespace()),
        "DeserialzieRozuctovanieMzdy"
    );

    addItemsToVyplatnePasky(formattedAreaPairReport, ref _pasky);
    return _pasky;
}

public static List<VyplatnePasky> DeserializeVyplatnePasky(string sPath)
{
    List<VyplatnePasky> _pasky = new List<VyplatnePasky>();

    var formattedAreaPairReport =
    tryToGetItemsFromDocument
    (
        sPath,
        document=>from d in document.Descendants("FormattedReport".AddNamespace())
                  select d.Element("FormattedAreaPair".AddNamespace()),
        "DeserializeVyplatnePasky"
    );
    addItemsToVyplatnePasky2(formattedAreaPairReport, _pasky);
    return _pasky;
}

private static void addItemsToVyplatnePasky(IEnumerable<XElement> formattedAreaPairReport, ref List<VyplatnePasky> _pasky)
{
    if (formattedAreaPairReport.Count() > 0)
    {
        //check if any sequence contains any matching elements
        var GotElements = formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()).Where(n=>n.Attribute("Level").Value == "3" && n.Attribute("Type").Value == "Group");
        if (GotElements == null)
        {
            InsertErrorMessage("There are no matching elements under <formattedAreaPairReport>.", "DeserialzieRozuctovanieMzdy");
            return;
        }

        foreach (XElement xElement in GotElements)
        {
            RozuctovanieMzda_Values(xElement, ref _pasky);
        }
    }

}

private static void addItemsToVyplatnePasky2(IEnumerable<XElement> formattedAreaPairReport, List<VyplatnePasky> _pasky)
{
    foreach (XElement xElement in formattedAreaPairReport.Elements("FormattedAreaPair".AddNamespace()))
    {
        VyplatnePasky _paska = new VyplatnePasky();
        VyplatnePasky_Items(xElement, ref _paska);

        _pasky.Add(_paska);
    }
}

private static IEnumerable<XElement> tryToGetItemsFromDocument(string sPath, Func<XDocument, IEnumerable<XElement>> query, string name)
{
    XDocument document = XDocument.Load(sPath);
    var report = query(document);
    if (report.Count() == 0)
    {
        //empty;
        InsertErrorMessage("<formattedAreaPairReport> contains no data! No Data to parse from.", name);
    }
    return report;
}

本質上,您可以繼續分解代碼,然后尋找重復的習慣用法進行清理。 在該清理過程中,泛型可能會起作用,也可能不會起作用。 另外,您可能想給這些方法命名比我更好的名稱,因為我不熟悉此代碼中使用的本機語言。 :-)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM