I am having following type of XML:
Through this XML I wish to populate following objectList.
List<Function> objFunctionsList = new List<Function>();
where Function class is as follows,
public class Function
{
public String Name { get ; set; }
public Parameter ReturnType { get; set; }
public List<Parameter> Parameters { get; set; }
public String Library { get; set; }
public String Signature { get; set; }
public String Description { get; set; }
public String Code { get; set; }
}
and the Parameter class is as follows,
public class Parameter
{
[DefaultValue("")]
public String Name { get; set; }
[DefaultValue("")]
public String DataType { get; set; }
[DefaultValue("")]
public String OccurenceType { get; set; }
}
You can see that in XML some function tags have Parameters tag while some others do not. I have tried this:
public const string XPATH_NAME = "/Functions/Function/Name";
public const string XPATH_LIBRARY = "/Functions/Function/Library";
public const string XPATH_SIGNATURE = "/Functions/Function/Signature";
public const string XPATH_DESCRIPTION = "/Functions/Function/Description";
public const string XPATH_CODE = "/Functions/Function/Code";
List<Function> objFunctionsList = new List<Function>();
try
{
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(pXMLPath);
XmlNodeList nlName = xmlDoc.SelectNodes(Constants.XPATH_NAME);
XmlNodeList nlLibrary = xmlDoc.SelectNodes(Constants.XPATH_LIBRARY);
XmlNodeList nlSignature = xmlDoc.SelectNodes(Constants.XPATH_SIGNATURE);
XmlNodeList nlDescription = xmlDoc.SelectNodes(Constants.XPATH_DESCRIPTION);
XmlNodeList nlCode = xmlDoc.SelectNodes(Constants.XPATH_CODE);
// Name, Signature, Library, element should be present in 'Function' node
if (nlName.Count == nlLibrary.Count
&& nlName.Count == nlSignature.Count
&& nlName.Count == nlDescription.Count
&& nlName.Count == nlCode.Count)
{
for (int iCount = 0; iCount < nlName.Count; iCount++)
{
Function objFunction = new Function();
objFunction.Name = nlName[iCount].InnerText.Trim();
objFunction.Library = nlLibrary[iCount].InnerText.Trim();
string signature = nlSignature[iCount].InnerText;
Parameter objReturnType = new Parameter();
string returnType = (nlSignature[iCount].Attributes[Constants.ATRR_TYPE] == null
? Constants.XSNOPARAM
: nlSignature[iCount].Attributes[Constants.ATRR_TYPE].Value);
if (returnType.EndsWith(Constants.ASTERIK))
{
objReturnType.DataType = returnType.Substring(0, returnType.Length - 1);
objReturnType.OccurenceType = Constants.OCCURENCES_ASTERISK;
}
else if (returnType.EndsWith(Constants.PLUS))
{
objReturnType.DataType = returnType.Substring(0, returnType.Length - 1);
objReturnType.OccurenceType = Constants.OCCURENCES_PLUS;
}
else if (returnType.EndsWith(Constants.QUESTION_MARK))
{
objReturnType.DataType = returnType.Substring(0, returnType.Length - 1);
objReturnType.OccurenceType = Constants.OCCURENCES_QUESTION;
}
else if (returnType.Length > 0)
{
objReturnType.DataType = returnType;
}
objFunction.ReturnType = objReturnType;
objFunction.Parameters = new List<Parameter>();
objFunction.Signature = signature;
objFunction.Description = nlDescription[iCount].InnerText.Trim();
objFunction.Code = nlCode[iCount].InnerText.Trim();
objFunctionsList.Add(objFunction);
}
}
}
but this is XPath based code and was in use earlier when I was not having Parameters Tag in the function tag.
As the article that @NitinRastogi mentions in his answer points out, you can use some convenient properties of LINQ to make it easy to work around null
or optional values:
Methods that return collections, such as Elements()
, will return an empty collection (not null
) if no results are found or they're passed empty collections as input:
If an empty collection is passed to the
Attributes
extension method, it also returns an empty collection.
Some LINQ mehods that return a single value, such as First()
, also have variants that will return a default value, such as null
, if no object is found, instead of raising an exception. In the case of First()
, its variant is FirstOrDefault()
.
So in your case, since Parameters
are optional for your Function
objects, you can choose to either initialize them with Parameters
equal to null
or an empty list.
null
If you want to initialize them as null
, you can do this:
var doc = // XDocument.Load() or XDocument.Parse() ...
var functions =
from f in doc.Root.Elements()
select new
{
// ...
Parameters = f.Elements("parameters").Elements().Count() == 0
? null
: (
from p in f.Elements("parameters").Elements()
select new {
DataType = p.Attribute("type"),
Name = p.Attribute("name"),
Occurence = p.Attribute("occurence")
})
.ToList()
// ...
};
But that results in a lot of ugly null
checking code. A simpler approach would be to just initialize with a list that contains 0 or more elements. These LINQ and XElement
collection methods will all return an empty collection if there are no parameters, so that the Parameters
property on your functions will just be an empty list instead of null:
var doc = // XDocument.Load() or XDocument.Parse() ...
var functions =
from f in doc.Root.Elements()
select new
{
// ...
Parameters = (
from p in f.Elements("parameters").Elements()
select new {
DataType = p.Attribute("type"),
Name = p.Attribute("name"),
Occurence = p.Attribute("occurence")
})
.ToList()
// ...
};
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.