Как правильно анализировать XML-документ с произвольными пространствами имен - PullRequest
7 голосов
/ 20 октября 2010

Я пытаюсь проанализировать несколько стандартных XML-документов, которые используют схему под названием MARCXML из различных источников.

Вот несколько первых строк примера 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>

Ключевой момент: , чтобы заставить XPath разрешать дальше вЯ должен пройти процедуру регулярных выражений, чтобы добавить пространства имен в таблицу имен (которая по умолчанию не добавляет их).Это кажется мне ненужным.

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!

1 Ответ

2 голосов
/ 20 октября 2010

Если вы знаете , то в документе будет данный элемент (например, корневой элемент), вы можете попробовать использовать GetNamespaceOfPrefix .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...