Estoy tratando de analizar documentos XML algo estándar que usan un esquema llamado MARCXML de varias fuentes.Cómo analizar correctamente un documento XML con espacios de nombres arbitrarios
Estas son las primeras líneas de un archivo XML de ejemplo que debe ser manejada ...
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<marc:collection xmlns:marc="http://www.loc.gov/MARC21/slim" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd">
<marc:record>
<marc:leader>00925njm 22002777a 4500</marc:leader>
y otro sin prefijos de espacio de nombres ...
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
<record>
<leader>01142cam 2200301 a 4500</leader>
Punto clave: Para que los XPath se resuelvan aún más en el programa, tengo que pasar por una rutina de expresiones regulares para agregar los espacios de nombres a NameTable (que no los agrega de manera predeterminada). Esto me parece innecesario.
Regex xmlNamespace = new Regex("xmlns:(?<PREFIX>[^=]+)=\"(?<URI>[^\"]+)\"", RegexOptions.Compiled);
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlRecord);
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmlDoc.NameTable);
MatchCollection namespaces = xmlNamespace.Matches(xmlRecord);
foreach (Match n in namespaces)
{
nsMgr.AddNamespace(n.Groups["PREFIX"].ToString(), n.Groups["URI"].ToString());
}
La llamada XPath se ve algo como esto ...
XmlNode leaderNode = xmlDoc.SelectSingleNode(".//" + LeaderNode, nsMgr);
Dónde LeaderNode
es un valor configurable y sería igual a "marc:leader"
en el primer ejemplo y "leader"
en el segundo ejemplo.
¿Existe alguna forma mejor y más eficiente de hacerlo? Nota: sugerencias para resolver esto usando LINQ son bienvenidas, pero principalmente me gustaría saber cómo resolver esto usando XmlDocument
.
EDIT: seguí el consejo de GrayWizardx y ahora tienen el siguiente código ...
if (LeaderNode.Contains(":"))
{
string prefix = LeaderNode.Substring(0, LeaderNode.IndexOf(':'));
XmlNode root = xmlDoc.FirstChild;
string nameSpace = root.GetNamespaceOfPrefix(prefix);
nsMgr.AddNamespace(prefix, nameSpace);
}
Ahora no hay más dependencia de la expresión regular!
Estoy enfrentando casi el mismo problema. ¿Cómo logras tu magia 'LeaderNode'? ¿Tiene precognición de qué tipo de registro está tratando? –