断言从 XML 解析的元素

发布于 2024-12-23 15:12:52 字数 608 浏览 1 评论 0原文

我有一个使用 XElement 在 C# 中解析 XML 文档的类。

例如,我解析 XML:

IEnumerable<Element> elements =
    from topLevelElement in XElement.Parse(xml).Elements("topLevel")
    select new Element()
    {
        LongElement = Int64.Parse(topLevelElement.Element("long").Value),
        StringElement = topLevelElement.Element("string").Value,
        DateTimeElement = DateTime.Parse(topLevelElement.Element("datetime").Value)
    };

断言元素已正确解析的最佳方法是什么?我想检查解析后 LongElementStringElementDateTimeElement 是否不为 null,但是否有更好的方法来解决此问题,我对此持开放态度。

I have a class that parses an XML document in C# using XElement.

I parse the XML for example:

IEnumerable<Element> elements =
    from topLevelElement in XElement.Parse(xml).Elements("topLevel")
    select new Element()
    {
        LongElement = Int64.Parse(topLevelElement.Element("long").Value),
        StringElement = topLevelElement.Element("string").Value,
        DateTimeElement = DateTime.Parse(topLevelElement.Element("datetime").Value)
    };

What would be the best way to assert that the elements were properly parsed? I would like to check if LongElement, StringElement, and DateTimeElement is not null after parsing, but if there is a better way to go about this, I am open to it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

吻风 2024-12-30 15:12:52

如果您不确定元素可能返回的值,那么您确实应该使用 TryParse,例如,

int i = 0;
string s = "3";
if (Int32.TryParse(s, out i))
{
    // Valid integer, now stored in i.
}
else
{
    // Invalid integer.
}

您的数据类型 DateTime 和 Int32 都将 TryParse 作为可用方法。对于字符串,您只需执行简单的 == nullString.IsNullOrEmpty

If you are unsure of the values that may be returned by the elements, you should really be using TryParse e.g.

int i = 0;
string s = "3";
if (Int32.TryParse(s, out i))
{
    // Valid integer, now stored in i.
}
else
{
    // Invalid integer.
}

Both your data types DateTime and Int32 have TryParse as an available method. As for a string, you can just do a trivial == null or String.IsNullOrEmpty

今天小雨转甜 2024-12-30 15:12:52

我会使用 Linq 中的函数。如果您希望应用程序不那么严格,这些允许您抛出异常或设置所需的默认值;)

无论如何,您可以获得更多控制:

var elements = from topLevelElement in XElement.Parse(xml).Elements("topLevel")
               select new Element()
               {
                   LongElement = ConvertToInt(topLevelElement.Element("long").Value),
                   StringElement = topLevelElement.Element("string").Value,
                   DateTimeElement = DateTime.Parse(topLevelElement.Element("datetime").Value)
               };

ConvertToInt 中可以完成您想要的所有操作,例如

    public int ConvertToInt(object value)
    {
       if(value is int)
         // return converted value
       else
         // return default, throw exception, etc
    }

:也是一种更可重用的布局。

I would use functions from within Linq. These allow you to either throw an exception or set required defaults if you want your application to be not so strict ;)

Anyways, you get more control:

var elements = from topLevelElement in XElement.Parse(xml).Elements("topLevel")
               select new Element()
               {
                   LongElement = ConvertToInt(topLevelElement.Element("long").Value),
                   StringElement = topLevelElement.Element("string").Value,
                   DateTimeElement = DateTime.Parse(topLevelElement.Element("datetime").Value)
               };

Where within ConvertToInt could do all you want, like:

    public int ConvertToInt(object value)
    {
       if(value is int)
         // return converted value
       else
         // return default, throw exception, etc
    }

This is also a more reusable layout.

小伙你站住 2024-12-30 15:12:52

我会将解析状态存储在元素中作为 KeyValuePair:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;


namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var states = new string[] { "null", "empty", "noparse", "value" };
            var xml = "<root>";
            xml += "<topLevel><long>-13451245234</long><string>hello world</string><datetime>1/1/2012 8:00AM</datetime></topLevel>";
            xml += "<topLevel><long>4563264643</long><string>lipsum</string><datetime></datetime></topLevel>";
            xml += "<topLevel><string>hello world</string><datetime>1/1/2012 8:00AM</datetime></topLevel>";
            xml += "</root>";

        IEnumerable<Element> elements =
            from topLevelElement in XElement.Parse(xml).Elements("topLevel")
            select new Element
                       {
                           LongElement = ParseValue(topLevelElement, "long"),
                           DateTimeElement = ParseValue(topLevelElement, "datetime"),
                           StringElement = ParseValue(topLevelElement, "string"),
                       };

        var idx = 0;
        elements.All(e =>
        {
            Console.WriteLine("---- ELEMENT #{0} -----",idx++);
            Console.WriteLine("[long]     State: {0}\tValue:{1}\tType:{2}", states[e.LongElement.Key], e.LongElement.Value, (e.LongElement.Value).GetType());
            Console.WriteLine("[datetime] State: {0}\tValue:{1}\tType:{2}", states[e.DateTimeElement.Key], e.DateTimeElement.Value, (e.DateTimeElement.Value).GetType());
            Console.WriteLine("[string]   State: {0}\tValue:{1}\tType:{2}", states[e.StringElement.Key], e.StringElement.Value, (e.StringElement.Value).GetType());


            return true;
        });
    }

    private static dynamic ParseValue(XElement parent, String propname)
    {
        var prop = parent.Element(propname);
        dynamic val = null;
        byte state = 255;
        if (prop == null) state = 0;
        else if (string.IsNullOrEmpty(prop.Value)) state = 1;
        if (state < 255) return GetKVP(propname, state, GetDefaultValue(propname));


        switch (propname)
        {
            case "string":
                state = 3;
                val =  prop.Value;
                break;
            case "long":
                Int64 longvalue;
                if (Int64.TryParse(prop.Value, out longvalue)) { state = 3; val = longvalue; }
                else state = 2;
                break;
            case "datetime":
                DateTime datetimevalue;
                if (DateTime.TryParse(prop.Value, out datetimevalue)) { state = 3; val = datetimevalue; }
                else state = 2;
                break;
            default:
                val = GetDefaultValue(propname);
                break;
        }


        return GetKVP(propname,state,val);
    }

    private static dynamic GetKVP(string propname, byte state, object val)
    {
        if (propname == "long") return new KeyValuePair<byte, Int64>(state, (Int64)val);
        if (propname == "datetime") return new KeyValuePair<byte, DateTime>(state, (DateTime)val);
        if (propname == "string") return new KeyValuePair<byte, String>(state, (String)val);
        return null;

    }
    private static dynamic GetDefaultValue(string propname)
    {
        if (propname == "long") return long.MinValue;
        if (propname == "datetime") return DateTime.MinValue;
        if (propname == "string") return null;
        return null;

    }

    #region Nested type: Element

    public struct Element
    {
        // States stored as byte, 0 = null, 1= empty, 2 = has a value
        public KeyValuePair<byte,Int64> LongElement { get; set; }
        public KeyValuePair<byte,String> StringElement { get; set; }
        public KeyValuePair<byte,DateTime> DateTimeElement { get; set; }

    }

    #endregion
}
}

I would store the parse states in the element as a KeyValuePair:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;


namespace ConsoleApplication1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var states = new string[] { "null", "empty", "noparse", "value" };
            var xml = "<root>";
            xml += "<topLevel><long>-13451245234</long><string>hello world</string><datetime>1/1/2012 8:00AM</datetime></topLevel>";
            xml += "<topLevel><long>4563264643</long><string>lipsum</string><datetime></datetime></topLevel>";
            xml += "<topLevel><string>hello world</string><datetime>1/1/2012 8:00AM</datetime></topLevel>";
            xml += "</root>";

        IEnumerable<Element> elements =
            from topLevelElement in XElement.Parse(xml).Elements("topLevel")
            select new Element
                       {
                           LongElement = ParseValue(topLevelElement, "long"),
                           DateTimeElement = ParseValue(topLevelElement, "datetime"),
                           StringElement = ParseValue(topLevelElement, "string"),
                       };

        var idx = 0;
        elements.All(e =>
        {
            Console.WriteLine("---- ELEMENT #{0} -----",idx++);
            Console.WriteLine("[long]     State: {0}\tValue:{1}\tType:{2}", states[e.LongElement.Key], e.LongElement.Value, (e.LongElement.Value).GetType());
            Console.WriteLine("[datetime] State: {0}\tValue:{1}\tType:{2}", states[e.DateTimeElement.Key], e.DateTimeElement.Value, (e.DateTimeElement.Value).GetType());
            Console.WriteLine("[string]   State: {0}\tValue:{1}\tType:{2}", states[e.StringElement.Key], e.StringElement.Value, (e.StringElement.Value).GetType());


            return true;
        });
    }

    private static dynamic ParseValue(XElement parent, String propname)
    {
        var prop = parent.Element(propname);
        dynamic val = null;
        byte state = 255;
        if (prop == null) state = 0;
        else if (string.IsNullOrEmpty(prop.Value)) state = 1;
        if (state < 255) return GetKVP(propname, state, GetDefaultValue(propname));


        switch (propname)
        {
            case "string":
                state = 3;
                val =  prop.Value;
                break;
            case "long":
                Int64 longvalue;
                if (Int64.TryParse(prop.Value, out longvalue)) { state = 3; val = longvalue; }
                else state = 2;
                break;
            case "datetime":
                DateTime datetimevalue;
                if (DateTime.TryParse(prop.Value, out datetimevalue)) { state = 3; val = datetimevalue; }
                else state = 2;
                break;
            default:
                val = GetDefaultValue(propname);
                break;
        }


        return GetKVP(propname,state,val);
    }

    private static dynamic GetKVP(string propname, byte state, object val)
    {
        if (propname == "long") return new KeyValuePair<byte, Int64>(state, (Int64)val);
        if (propname == "datetime") return new KeyValuePair<byte, DateTime>(state, (DateTime)val);
        if (propname == "string") return new KeyValuePair<byte, String>(state, (String)val);
        return null;

    }
    private static dynamic GetDefaultValue(string propname)
    {
        if (propname == "long") return long.MinValue;
        if (propname == "datetime") return DateTime.MinValue;
        if (propname == "string") return null;
        return null;

    }

    #region Nested type: Element

    public struct Element
    {
        // States stored as byte, 0 = null, 1= empty, 2 = has a value
        public KeyValuePair<byte,Int64> LongElement { get; set; }
        public KeyValuePair<byte,String> StringElement { get; set; }
        public KeyValuePair<byte,DateTime> DateTimeElement { get; set; }

    }

    #endregion
}
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文