c# without - ¿Comprobar XML bien formado sin un try / catch?




visual excepciones (9)

¿Alguien sabe cómo puedo verificar si una cadena contiene XML bien formado sin usar algo como XmlDocument.LoadXml() en un bloque try / catch? Tengo una entrada que puede o no ser XML, y quiero un código que reconozca que la entrada no sea XML sin confiar en un try / catch, tanto por la velocidad como por el principio general de que las circunstancias no excepcionales no deberían aumentar. excepciones Actualmente tengo un código que hace esto;

private bool IsValidXML(string value)
    {
        try
        {
            // Check we actually have a value
            if (string.IsNullOrEmpty(value) == false)
            {
                // Try to load the value into a document
                XmlDocument xmlDoc = new XmlDocument();

                xmlDoc.LoadXml(value);

                // If we managed with no exception then this is valid XML!
                return true;
            }
            else
            {
                // A blank value is not valid xml
                return false;
            }
        }
        catch (System.Xml.XmlException)
        {
            return false;
        }
    }

Pero parece algo que no debería requerir el try / catch. La excepción está causando un feliz infierno durante la depuración porque cada vez que reviso una cadena, el depurador se romperá aquí, "ayudándome" con mi molesto problema.


Answers

No conozco una forma de validar sin la excepción, pero puede cambiar la configuración del depurador para que solo se rompa para XmlException si no se XmlException , eso debería resolver sus problemas inmediatos, incluso si el código aún no es elegante.

Para hacer esto, vaya a Debug / Exceptions ... / Common Language Runtime Exceptions y encuentre la excepción System.Xml.XmlException, luego asegúrese de que solo esté marcado "No manejado por el usuario" (no arrojado).


Mis dos centavos. Esto fue bastante simple y sigue algunas convenciones comunes ya que se trata de analizar ...

public bool TryParse(string s, ref XmlDocument result)
{
    try {
        result = new XmlDocument();
        result.LoadXml(s);
        return true;
    } catch (XmlException ex) {
        return false;
    }
}

Steve,

Tuvimos una tercera parte que accidentalmente nos envió JSON en lugar de XML. Esto es lo que implementé:

public static bool IsValidXml(string xmlString)
{
    Regex tagsWithData = new Regex("<\\w+>[^<]+</\\w+>");

    //Light checking
    if (string.IsNullOrEmpty(xmlString) || tagsWithData.IsMatch(xmlString) == false)
    {
        return false;
    }

    try
    {
        XmlDocument xmlDocument = new XmlDocument();
        xmlDocument.LoadXml(xmlString);
        return true;
    }
    catch (Exception e1)
    {
        return false;
    }
}

[TestMethod()]
public void TestValidXml()
{
    string xml = "<result>true</result>";
    Assert.IsTrue(Utility.IsValidXml(xml));
}

[TestMethod()]
public void TestIsNotValidXml()
{
    string json = "{ \"result\": \"true\" }";
    Assert.IsFalse(Utility.IsValidXml(json));
}

Agregue el atributo [System.Diagnostics.DebuggerStepThrough] al método IsValidXml . Esto evita que el depurador capture la excepción XmlException, lo que significa que puede activar la captura de excepciones de primer cambio y este método en particular no se depurará.


Esa es una forma razonable de hacerlo, excepto que IsNullOrEmpty es redundante (LoadXml puede resolverlo bien). Si mantiene IsNullOrEmpty, haga if (! String.IsNullOrEmpty (value)).

Básicamente, sin embargo, su depurador es el problema, no el código.


Precaución con el uso de XmlDocument porque es posible cargar un elemento a lo largo de las líneas de <0>some text</0> usando XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(object) sin que se haya lanzado una excepción.

Los nombres de elementos numéricos no son xml válidos, y en mi caso no se produjo un error hasta que intenté escribir el xmlDoc.innerText en un tipo de datos del servidor Sql de xml.

Así lo valido ahora, y se lanza una excepción.
XmlDocument tempDoc = XmlDocument)JsonConvert.DeserializeXmlNode(formData.ToString(), "data"); doc.LoadXml(tempDoc.InnerXml);


Solo mis 2 centavos: hay varias preguntas sobre esto, y la mayoría de la gente está de acuerdo con el hecho de "basura en - basura fuera". No estoy en desacuerdo con eso, pero personalmente encontré la siguiente solución rápida y sucia, especialmente para los casos en los que tratas con datos xml de terceros que simplemente no se comunican contigo fácilmente. No evita el uso de try / catch, pero lo usa con una granularidad más fina, por lo que en los casos en que la cantidad de caracteres xml no válidos no es tan grande, ayuda .. Usé XmlTextReader y su método ReadChars () para cada elemento padre, que es uno de los comandos que no hacen chequeos bien formados, como ReadInner / OuterXml hace. Así que es una combinación de Read () y ReadChars () cuando Read () apuntala en un nodo padre. Por supuesto, esto funciona porque puedo suponer que la estructura básica del XML está bien, pero los contenidos (valores) de ciertos nodos pueden contener caracteres especiales que no se han reemplazado con & ..; equivalente ... (Encontré un artículo sobre esto en algún lugar, pero no puedo encontrar el enlace de fuente en este momento)


No estoy de acuerdo en que el problema sea el depurador. En general, para casos no excepcionales, deben evitarse las excepciones. Esto significa que si alguien está buscando un método como IsWellFormed() que devuelve verdadero / falso en función de si la entrada está bien formada en XML o no, no se deben lanzar excepciones dentro de esta implementación, independientemente de si se detectan y manejan o no. .

Las excepciones son caras y no deben encontrarse durante la ejecución normal exitosa. Un ejemplo es escribir un método que verifique la existencia de un archivo y usar File.Open y capturar la excepción en caso de que el archivo no exista. Esta sería una mala implementación. En File.Exists() lugar, se debe usar File.Exists() (y es de esperar que la implementación de eso no se File.Exists() a probar, sino a un método que arroje una excepción si el archivo no existe, estoy seguro de que no existe).


Si la captura es demasiado para usted, entonces es posible que desee validar el XML de antemano, utilizando un Esquema XML, para asegurarse de que el XML está bien, pero eso probablemente será peor que la captura.





c# xml well-formed