Как игнорировать значение NULL при сопоставлении xml - PullRequest
0 голосов
/ 17 июня 2020

У меня есть метод сопоставления с XML файлами. Оба XML имеют одинаковый ClientRefNr. Но я пытаюсь получить всю информацию от обоих и сопоставить ее с одним XML. Это нормально работает. но иногда в Doc1 есть идентификаторы, которых нет в Doc2 (NULL). И это то, что мне нужно, чтобы просто перепрыгнуть и продолжить.

XML1:

 <Table1>
    <Id>1581016</ClientRefNr>
    <Id>12</Id>
    <Value>All commentary</Value>
  </Table1>
  <Table1>
    <ClientRefNr>754030</ClientRefNr>
    <Id>17</Id>
    <Value>All commentary</Value>
  </Table1>

XML2:

 <Table1>
    <ClientRefNr>1581016</ClientRefNr>
    <Id>12</Id>
    <Name>All commentary</Name>
  </Table1>
  <Table1>
    <ClientRefNr>75885</ClientRefNr>
    <Id>11</Id>
    <Name>Martin</Name>
  </Table1>

То, что я пробовал с C#

    public XDocument MatchClientCommWithLZ(XDocument ClientCommXML, XDocument doc2)
    {
        XDocument result = new XDocument();
        List<XElement> doc1Elements = ClientCommXML.Root.Elements().ToList();
        List<XElement> doc2Elements = doc2.Root.Elements().ToList();


        XElement accountElement = new XElement("ClientRefNr");
        result = new XDocument(accountElement);

        for (int i = 0; i < doc1Elements.Count(); i++)
        {
            XmlDocument subDoc = new XmlDocument();
            subDoc.LoadXml(doc1Elements[i].ToString());

            string tableName = subDoc.FirstChild.Name;
            string ClientRefNr = doc1Elements[i].Elements().Where(x => x.Name == "ClientRefNr").FirstOrDefault().Value;



            List<XElement> doc1Childs = doc1Elements[i].Elements().ToList();
            List<XElement> doc2Childs = doc2Elements.Where(x => x.ToString().IndexOf(ClientRefNr) > -1).FirstOrDefault().Elements().ToList();

            XElement tblElement = new XElement(tableName);
            tblElement.Add(new XElement("Id", GetClientValue(doc1Childs, doc2Childs, "Id")));
            tblElement.Add(new XElement("ClientRefNr", GetClientValue(doc1Childs, doc2Childs, "ClientRefNr")));
            tblElement.Add(new XElement("Name", GetClientValue(doc1Childs, doc2Childs, "Name")));
            tblElement.Add(new XElement("Value", GetClientValue(doc1Childs, doc2Childs, "Value")));



            accountElement.Add(tblElement);

        }
        return result;
    }

И это прекрасно работает. Но когда я нажимаю ClientRefNr, где значение не существует в Doc2, я получаю эту ошибку

An unhandled exception of type 'System.NullReferenceException' because this is NULL

List<XElement> doc2Childs = doc2Elements.Where(x => x.ToString().IndexOf(ClientRefNr) > -1).FirstOrDefault().Elements().ToList();

Любые идеи, как игнорировать, если ClientRefNr не существует в Doc2

Ответы [ 3 ]

0 голосов
/ 17 июня 2020

Другое решение, если ваша C# -версия достаточно высока (т. Е. Не построена для очень старой. NET -версии), может быть использование ?. -оператора, который выполняет функцию, когда левая сторона не является нулем и возвращает null, если левая сторона равна null: doc2Elements.Where(x => x.ToString().IndexOf(ClientRefNr) > -1).FirstOrDefault()?.Elements()?.ToList();

Тогда doc2Childs будет null, когда FirstOrDefault вернет null.

Если вы хотите, чтобы это был пустой список, когда это произойдет, вы можете сделать doc2Elements.Where(x => x.ToString().IndexOf(ClientRefNr) > -1).FirstOrDefault()?.Elements()?.ToList() ?? new List<XElement>();

Это приведет к созданию нового списка, когда левая сторона будет null

To резюмируем: a ?? b - это сокращение от a == null ? b : a, а a?.b - сокращение от a == null ? null : a.b

0 голосов
/ 17 июня 2020

Есть 2 решения вашей проблемы, в зависимости от того, что вы хотите сделать, если вы обнаружите нулевое значение в одном из ваших XML файлов

  1. Игнорируйте его и переходите к
  2. Подтвердите и
    • Продолжите
    • Пропустить
    • Перерыв

1:

List<XElement> doc2Childs = doc2Elements.Where(x => x.ToString().IndexOf(ClientRefNr) > -1).FirstOrDefault()?.Elements()?.ToList();

Похоже, то же самое, что и у тебя, верно? Ну, есть небольшая разница, я использовал оператор условного доступа к члену , который:

применяет доступ к члену,?., Или доступ к элементу,? [], Операцию к его операнду, только если этот операнд не равен нулю; в противном случае он возвращает null

Это означает, что ваш List<XElement> doc2Childs может или не может быть нулевым после этой операции, поэтому следите за дальнейшими ошибками в строке


2:

var doc2TempResult = doc2Elements.Where(x => x.ToString().IndexOf(ClientRefNr) > -1).FirstOrDefault();

// Instead of continue, you could also break, or do whatever you want/ need
if (doc2TempResult is null || !(doc2TempResult.Elements() is IEnumerable<XElement> doc2Elements))
    continue;

var doc2Childs = doc2Elements.ToList()

Этот явно проверяет на null, он также проверяет, являются ли элементы doc2TempResult IEnumerable<XElement> (как указано методом Elements() здесь ) или не. Если это не так, он делает то же самое, как если бы временный результат был нулевым (вы можете разделить его на 2, если проверяет, хотите ли вы обрабатывать эти случаи по-другому). Затем он превращает IEnumerable в список, вызывая ToList(), как вы делали раньше

0 голосов
/ 17 июня 2020

Как насчет проверки, вернула ли функция Where какие-либо элементы? Изменить:

List<XElement> doc2Childs = doc2Elements.Where(x => x.ToString().IndexOf(ClientRefNr) > -1).FirstOrDefault().Elements().ToList();

Кому:

var tempResult = doc2Elements.Where(x => x.ToString().IndexOf(ClientRefNr) > -1).FirstOrDefault();
if(tempResult==null || tempResult.Elements() == null) 
   continue;

//... rest of the code
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...