Я пытаюсь разобрать несколько стандартных XML-документов, которые используют схему с именем MARCXML из разных источников.Как правильно разобрать XML-документ с произвольными пространствами имен
Вот первые несколько строк примера XML-файла, который должен быть обработан ...
<?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>
и один без префиксов ...
<?xml version="1.0" encoding="UTF-8" standalone="no" ?>
<collection xmlns="http://www.loc.gov/MARC21/slim">
<record>
<leader>01142cam 2200301 a 4500</leader>
Ключевой момент: чтобы получить XPaths для дальнейшего решения в программе, я должен пройти процедуру регулярного выражения, чтобы добавить пространства имен в NameTable (который не добавляет их по умолчанию). Мне это кажется ненужным.
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());
}
вызов XPath выглядит примерно так ...
XmlNode leaderNode = xmlDoc.SelectSingleNode(".//" + LeaderNode, nsMgr);
Где LeaderNode
конфигурируемый значение и будет равна "marc:leader"
в первом примере и "leader"
во втором примере.
Есть ли лучший, более эффективный способ сделать это? Примечание. Предложения по его решению с использованием LINQ приветствуются, но в основном я хотел бы знать, как это решить, используя XmlDocument
.
EDIT: Я принял совет GrayWizardx и теперь имеют следующий код ...
if (LeaderNode.Contains(":"))
{
string prefix = LeaderNode.Substring(0, LeaderNode.IndexOf(':'));
XmlNode root = xmlDoc.FirstChild;
string nameSpace = root.GetNamespaceOfPrefix(prefix);
nsMgr.AddNamespace(prefix, nameSpace);
}
Теперь больше нет зависимости от Regex!
Я столкнулся с почти той же проблемой. Как вы справляетесь с магией «LeaderNode»? Есть ли у вас предвидение какого типа записи вы имеете дело? –