Sto cercando di analizzare documenti XML standard in qualche modo che utilizzano uno schema chiamato MARCXML da varie origini.Come analizzare correttamente un documento XML con spazi dei nomi arbitrari
Ecco le prime righe di un file XML di esempio che deve essere gestita ...
<?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>
e uno senza prefissi di namespace ...
<?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 chiave: per far sì che gli XPath si risolvano ulteriormente nel programma devo passare attraverso una routine regolare per aggiungere gli spazi dei nomi al NameTable (che non li aggiunge per impostazione predefinita). Questo mi sembra non necessario.
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 chiamata XPath simile a questa ...
XmlNode leaderNode = xmlDoc.SelectSingleNode(".//" + LeaderNode, nsMgr);
Dove LeaderNode
è un valore configurabile e sarebbe uguale "marc:leader"
nel primo esempio e "leader"
nel secondo esempio.
Esiste un modo migliore, più efficiente per farlo? Nota: i suggerimenti per risolvere questo problema utilizzando LINQ sono i benvenuti, ma vorrei principalmente sapere come risolvere questo problema utilizzando XmlDocument
.
EDIT: ho preso il consiglio di GrayWizardx e ora hanno il seguente codice ...
if (LeaderNode.Contains(":"))
{
string prefix = LeaderNode.Substring(0, LeaderNode.IndexOf(':'));
XmlNode root = xmlDoc.FirstChild;
string nameSpace = root.GetNamespaceOfPrefix(prefix);
nsMgr.AddNamespace(prefix, nameSpace);
}
Ora non c'è più dipendenza da Regex!
Sto affrontando quasi lo stesso identico problema. Come realizzi la tua magia 'LeaderNode'? Hai la precognizione di quale tipo di record hai a che fare? –