0

I know Json.net has an attribute [JsonRequired]; are there any XML methods that can do the same thing?.

I don't think there is, so I have made my own way of doing so, but I have stopped at how to handle List and T in reflection.

It's a great help if someone will tell me, thanks.

class Program
{
    static void Main(string[] args)
    {
        string strin = "<TestXML><Fir>f</Fir><TestXML1><TestXML3><For>444</For></TestXML3></TestXML1></TestXML>";
        TestXML ttt1 = XmlToModel<TestXML>(strin);
        Console.ReadKey();
    }
    public static T XmlToModel<T>(string xml)
    {
        StringReader xmlReader = new StringReader(xml);
        XmlSerializer xmlSer = new XmlSerializer(typeof(T));
        T t = (T)xmlSer.Deserialize(xmlReader);
        Type typeT = typeof(T);
        IfIsClass<T>(typeT, t);
        return t;
    }
    private static void IfIsClass<T>(Type typeT, T t)
    {
        foreach (PropertyInfo p in typeT.GetProperties())
        {
            //here I don't konw how to handle List<T> and T

            //if(is List<T> or T)
            //  IfisClass<T>(typeT,t);
            IfIsNull<T>(p, t);
        }
    }
    private static void IfIsNull<T>(PropertyInfo p, T t)
    {
        var at = p.GetCustomAttribute(typeof(NotNullAttribute));
        var pvalue = p.GetValue(t);
        if (at != null && string.IsNullOrEmpty(pvalue == null ? "" : pvalue.ToString()))
        {
            throw new Exception(string.Format("Field {0} not allow null or empty", p.Name));
        }
    }
}
public class TestXML
{
    public string Fir { get; set; }
    [NotNull]
    public string Sec { get; set; }
    [XmlElement("")]
    public List<TestXML2> TestXML1 { get; set; }
}
public class TestXML2
{
    public string Thir { get; set; }
    public TestXML3 TestXML3 { get; set; }
}
public class TestXML3
{
    [NotNull]
    public string For { get; set; }
}
public class NotNullAttribute : Attribute
{
}
Abob
  • 751
  • 5
  • 27
plcly
  • 21
  • 4
  • What's wrong with what you're doing right now? What exactly are you trying to accomplish? – Abob May 19 '16 at 01:59
  • forgive my poor english... deserialize xml ,if(property==null) throw new Exception – plcly May 19 '16 at 02:13

3 Answers3

1

I don't 100% know what you're trying to accomplish with what you're doing right now, and I also don't know which values you don't want to be null, but I do see that there is a much easier way of deserialzing XML into objects (see here for some reference):

[XmlRoot("TestXML")]
public class TestXML
{
    [XmlElement("Fir")]
    public string Fir { get; set; }

    [XmlArray("TestXML1")]
    [XmlArrayItem("TestXML3", IsNullable = false)]
    public TestXML3[] testxml3 { get; set; }
}

public class TestXML3
{
    [XmlElement("For")]
    public int For { get; set; }
}

public class Order
{
    [XmlElement("number")]
    public string Number { get; set; }
}

Once you have that, you can deserialize the xml wherever you want in the same file with:

string xml = @"<TestXML><Fir>f</Fir><TestXML1><TestXML3><For>444</For></TestXML3></TestXML1></TestXML>";
StringReader reader = new StringReader(xml);
XmlSerializer ser = new XmlSerializer(typeof(TestXML));
var data = (TestXML)ser.Deserialize(reader);

Null Checking

Using XML

Basically, you just add IsNullable = false inside the parenthesis of a [XmlArrayItem], for example, to make sure a specific value will not return null (It will skip over it). NOTE: I have only tested this on [XmlArrayItem], I do not know for sure if it will work on other Xml tags...

Using C#

If you really wanted to use C# and throw and exception if it's null (which sort of ruins the point of using [XmlElement] in the first place), you can do something like this instead (see here):

... //same code as before
var data = (TestXML)ser.Deserialize(reader);
//haven't tested this
foreach(obj dataobj in data){
    if(dataobj == null) throw new NullReferenceException();
}

Using JSON

If you really want to use something like [JsonRequired], then why not just use it! You can convert the XML data to JSON data using Json.Net (see here):

string xml = @"<TestXML><Fir>f</Fir><TestXML1><TestXML3><For>444</For></TestXML3></TestXML1></TestXML>";
XmlDocument Test = new XMLDocument();
Test.loadXml(xml);
string json = JsonConvert.SerializeXmlNode(Test);

Now, you have your xml data in json format in string json, and you can do whatever you want to it, including setting up a map like I did with the xml and adding [JsonRequired]

Community
  • 1
  • 1
Abob
  • 751
  • 5
  • 27
  • Thanks for answer,I run your code,it doesn't useful for me. when xml node not exists,it will skip. I want to required Sec and For(like I has a [NotNull] attribute on it), when the "xml" do not have a value,I want deserialize failed. The Newtonsoft.Net has a atttibute [JsonRequired] can work. It seems I need to read the open source,and rewrite deserialize If I can. And thank you all the same. – plcly May 19 '16 at 03:39
  • @plcly did the second method not work either (using the `foreach` loop)? – Abob May 19 '16 at 03:41
  • @plcly If you really need something like [JsonRequired], why not just use it? you can convert the xml into json and then use those properties as you would with any json data. However, I would only recommend that if no other methods that I have in my answer work. – Abob May 19 '16 at 03:48
  • But I also need some field null,convert the xml into json seems good. – plcly May 19 '16 at 03:52
  • @plcly okay, I'll add that to my answer – Abob May 19 '16 at 03:53
0

someone told me,here is the answer.

 public static T XmlToModel<T>(string xml)
    {
        StringReader xmlReader = new StringReader(xml);
        XmlSerializer xmlSer = new XmlSerializer(typeof(T));
        T t = (T)xmlSer.Deserialize(xmlReader);
        Type typeT = typeof(T);
        IfIsClass(t);
        return t;
    }
    private static void IfIsClass(object t)
    {
         var typeT = t.GetType();
        foreach (PropertyInfo p in typeT.GetProperties())
        {
            if (typeof(System.Collections.ICollection).IsAssignableFrom(p.PropertyType))
            {
                var vValue = p.GetValue(t, null) as System.Collections.ICollection;
                foreach(var item in vValue )
                {
                    IfIsClass(item);
                }
            }
            else
            {
                IfIsNull(p, p.GetValue(t, null));
            }
        }
    }
    private static void IfIsNull(PropertyInfo p, object pvalue)
    {
        var at = p.GetCustomAttribute(typeof(NotNullAttribute));
        if (at != null && string.IsNullOrEmpty(pvalue == null ? "" : pvalue.ToString()))
        {
            throw new Exception(string.Format("field[{0}]not allow null or empty", p.Name));
        }
    }
plcly
  • 21
  • 4
-5

Add a constructor

public TestXML()
{
   Sec = "";
}
Carlos Leyva
  • 101
  • 2