Pergunta

I am using the following query to convert XML to a struct. If an element does not exist how would I accommodate for it in the following query(ClntCde will always exist but there is a chance Title will not exist)

ClientTbl ClientData = clientNode.Select(x => new ClientTbl
    {        
        ClientCode = x.Elements().Where(e => e.Name.LocalName == "ClntCde").FirstOrDefault().Value,
        //Title = x.Elements().Where(e => e.Name.LocalName == "Title").ToString(),
        //Title = x.Elements().Where(e => e.Name.LocalName == "Title").FirstOrDefault().Value,
        //Title = x.Elements("Title").FirstOrDefault().Value,                                                            
    }
).First();

The XML:

<Client xmlns="http://www.website.co.za/namespace">
    <ClntCde>0000013</ClntCde>
    <Surname>Account Holder Surname</Surname>
    <Address>
         <Addr1>.</Addr1>
         <Addr2>.</Addr2>
         <Addr3>.</Addr3>
         <Addr4>.</Addr4>
         <PostCde>2000</PostCde>
    </Address>
    <ClntAccTyp>A</ClntAccTyp>
    <ElecInd>NO</ElecInd>
    <Lang>ENG</Lang>
</Client>
Foi útil?

Solução 2

Title = (String)x.Elements()
                 .Where(e => e.Name.LocalName == "Title")
                 .Single();

OR

delcare namepace

XNamespace ns="http://www.website.co.za/namespace";

and refer it

Title = (String)x.Element(ns+"Title")

Outras dicas

You can use DefaultIfEmpty(""):

ClientCode = x.Elements()
    .Where(e => e.Name.LocalName == "ClntCde")
    .Select(e => e.Value)
    .DefaultIfEmpty("")
    .First(),
Title = x.Elements()
    .Where(e => e.Name.LocalName == "Title")
    .Select(e => e.Value)
    .DefaultIfEmpty("")
    .First(),
// ...

Note that the ...OrDefault is redundant if you provide a default value yourself. It is safe to call First or Single(can still throw on multiple elements) since it can never be empty.

Try:

Title = x.Elements()
 .Where(e => e.Name.LocalName == "Title")
 .Select(e => e.Value)
 .FirstOrDefault() ?? string.Empty;
var ns = clientNode.GetDefaultNamespace();
ClientTbl ClientData = clientNode.Select(x => new ClientTbl
    {        
        ClientCode = (string)x.Element(ns + "ClntCde") ?? string.Empty,
        Title = (string)x.Element(ns + "Title") ?? string.Empty,
    }
).First();

Update 1: added default namespace

Update 2: added blank string if element does not exists

Using this XML Library you can reference each element directly and give a default value if it doesn't exist like so:

ClientTbl ClientData = clientNode.Select(x => new ClientTbl
    {        
        ClientCode = x.Get("ClntCde", "defaultCode"),
        Title = x.Get("Title", "defaultTitle"),
        Addr1 = x.Get("Address/Addr1", "addr1 default"),
        // and/or
        Address = x.GetElement("Address") // Creates the Address node if doesn't exist
                   .Select(a => new
            {
                Addr1 = a.Get("Addr1", "addr1 default"),
                // etc
            })
    });

The default is type specific. If your code is always numeric, you can use a numeric default and it will be that type. Get also handles the namespace.

Get has the syntax of (in this case):

T Get<T>(string name, T defaultValue);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top