Проверьте, существует ли раздел xml в файле с помощью XDocument - PullRequest
0 голосов
/ 23 октября 2019

У меня есть код, который читает в XML-файле. Однако это вызывает ошибку в 3-м операторе IF:

if (xdoc.Root.Descendants("HOST").Descendants("Default")
    .FirstOrDefault().Descendants("HostID")
    .FirstOrDefault().Descendants("Deployment").Any())

Ошибка:

System.NullReferenceException: Object reference not set to an instance of an object.

Это потому, что в этом конкретном файле нет [HOST] раздел.

Я предполагал, что в первом операторе IF, если он не найдет ни одного раздела [HOST], он не войдет в оператор и, следовательно, я не должен получить эту ошибку. Есть ли способ проверить, существует ли раздел первым?

XDocument xdoc = XDocument.Load(myXmlFile);

if (xdoc.Root.Descendants("HOST").Any())
{
    if (xdoc.Root.Descendants("HOST").Descendants("Default").Any())
    {
        if (xdoc.Root.Descendants("HOST").Descendants("Default").FirstOrDefault().Descendants("HostID").FirstOrDefault().Descendants("Deployment").Any())
        {
            if (xdoc.Root.Descendants("HOST").Descendants("Default").FirstOrDefault().Descendants("HostID").Any())
            {
                var hopsTempplateDeployment = xdoc.Root.Descendants("HOST").Descendants("Default").FirstOrDefault().Descendants("HostID").FirstOrDefault().Descendants("Deployment").FirstOrDefault();
                deploymentKind = hopsTempplateDeployment.Attribute("DeploymentKind");
                host = hopsTempplateDeployment.Attribute("HostName");
            }
        }
    }
}

1 Ответ

1 голос
/ 23 октября 2019

Внутри этого блока if ...

if (xdoc.Root.Descendants("HOST").Descendants("Default").Any())
{
    if (xdoc.Root.Descendants("HOST").Descendants("Default").FirstOrDefault().Descendants("HostID").FirstOrDefault().Descendants("Deployment").Any())
    {
        if (xdoc.Root.Descendants("HOST").Descendants("Default").FirstOrDefault().Descendants("HostID").Any())
        {
            var hopsTempplateDeployment = xdoc.Root.Descendants("HOST").Descendants("Default").FirstOrDefault().Descendants("HostID").FirstOrDefault().Descendants("Deployment").FirstOrDefault();
            deploymentKind = hopsTempplateDeployment.Attribute("DeploymentKind");
            host = hopsTempplateDeployment.Attribute("HostName");
        }
    }
}

... вы установили, что элемент <Root>/HOST/Default существует. Однако вы не знаете, существует ли <Root>/HOST/Default/HostId/Deployment. Если этого не произойдет, вы получите NullReferenceException как тот, который вы испытываете из-за использования FirstOrDefault. Как правило, рекомендуется использовать First в тех случаях, когда вы ожидаете, что элементы будут присутствовать, что даст вам как минимум лучшее сообщение об ошибке.

Если вы ожидаете, что элементы не будут присутствовать, простое решениеиспользовать ?. вдоль соответствующей оси LINQ2XML:

var hopsTemplateDeployment =
    xdoc.Root.Descendants("HOST").Descendants("Default").FirstOrDefault()
    ?.Descendants("HostID").FirstOrDefault()
    ?.Descendants("Deployment").FirstOrDefault();
if (hopsTemplateDeployment != null)
{
    deploymentKind = hopsTemplateDeployment.Attribute("DeploymentKind");
    host = hopsTemplateDeployment.Attribute("HostName");
}

Это также спасет вас от цепочки вложенных предложений if.

...