Pregunta ¿La mejor prueba para la existencia de XPath en un archivo XML?


Últimamente he estado usando XPathDocument y XNavigator para analizar un archivo XML para un XPath y atributo dados. Ha funcionado muy bien, cuando sé de antemano qué es XPath.

A veces, sin embargo, el XPath será uno de varios posibles valores de XPath, y me gustaría poder probar si existe o no un XPath dado.

En caso de que me esté equivocando la nomenclatura, esto es lo que llamo XPath, dado este blob XML:

<foo>
    <bar baz="This is the value of the attribute named baz">
</foo>

Podría estar buscando lo que estoy llamando una XPath de "// foo / bar" y luego leer el atributo "baz" para obtener el valor.

Ejemplo del código que uso para hacer esto:

XPathDocument document = new XPathDocument(filename);
XPathNavigator navigator = document.CreateNavigator();
XPathNavigator node = navigator.SelectSingleNode("//foo/bar");
if(node.HasAttributes)
{
    Console.WriteLine(node.GetAttribute("baz", string.Empty));
}

Ahora, si la llamada a navigator.SelectSingleNode falla, devolverá una NullReferenceException o una XPathException. Puedo capturar ambos y refactorizar lo anterior en una prueba para ver si un XPath dado devuelve una excepción, pero me preguntaba si había una forma mejor.

No vi nada obvio en el Intellisense. XPathNavigator tiene .HasAttributes y .HasChildren, pero a falta de iterar a través de la ruta un nodo a la vez, no veo nada más agradable de usar.


6
2017-10-28 22:09


origen


Respuestas:


Si has dado XPath válido pero no coincide con nada, SelectSingleNode no lo hará lanzar un NullReferenceException - Simplemente devolverá nulo.

Si pasa SelectSingleNode algo de XPath sintácticamente inválido, ahí es cuando lanzará un XPathException.

Por lo general, solo necesitaría probar si el valor devuelto era nulo o no.


10
2017-10-28 22:14



 var baz = navigator.SelectSingleNode("//foo/bar/@baz");
 if (baz != null) Console.WriteLine(baz);

1
2017-10-28 22:30



Creo que no es bueno crear un objeto XMLNode ejecutando navigator.SelectSingleNode (...).

Tienes que usar navigator.Evaluate () en su lugar:

if (Convert.ToBoolean(navigator.Evaluate(@"boolean(//foo/bar)"))) {...}

1
2017-10-21 16:01



De memoria, puede contener errores.

XDocument doc = XDocument.Load("foo.xml");

var att = from a in doc.Descendants("bar")
          select a.Attribute("baz")

foreach (var item in att) {
    if (item != null) { ... }
}

0
2017-10-28 22:17



Si node == null entonces node.HasAttributes arrojará un NullReferenceException. Esta situación ocurrirá cuando //foo/bar no coincide con ningún elemento en el documento XML.


0
2017-10-28 22:18



var node = XDocument.Load(filename)
                    .Descendants("bar")
                    .SingleOrDefault(e=>e.Attribute("baz") != null);

if (node != null) Console.WriteLine(node.Attribute("baz").Value);

0
2017-10-28 22:25



Probablemente sería más específico en mi xpath.

        var doc = XDocument.Load(fileName);

        var results = from r in doc.XPathSelectElements("/foo/bar[count(@baz) > 0]")
                      select r.Attribute("baz");

        foreach (String s in results)
            Console.WriteLine(s);

0
2017-10-28 22:34