Как я могу перечислить все пространство имен в XML?

Мое основное требование - получить значение элемента из файла XML, я использовал XMLDoxument.SelectSingleNode. Мой XML файл содержит некоторое пространство имен в заголовке, поэтому я использовал NameSpaceManager для добавления префикса пространства имен и использовал префикс для получения этого конкретного элемента. Теперь в моих XML файлах пространства имен меняются, я не хочу делать какое-либо жесткое кодирование, есть ли способ узнать все пространства имен, и я могу добавить его в NameSpaceManager.

Спасибо.

Ответ 1

Пространства имен можно найти где угодно внутри документа xml. Поэтому, чтобы извлечь все пространства имен и объявить их в XmlNamespaceManager, я сделал следующее:

public static XmlNamespaceManager getAllNamespaces(XmlDocument xDoc)
{
    XmlNamespaceManager result = new XmlNamespaceManager(xDoc.NameTable);

    IDictionary<string, string> localNamespaces = null;
    XPathNavigator xNav = xDoc.CreateNavigator();
    while (xNav.MoveToFollowing(XPathNodeType.Element))
    {
        localNamespaces = xNav.GetNamespacesInScope(XmlNamespaceScope.Local);
        foreach (var localNamespace in localNamespaces)
        {
            string prefix = localNamespace.Key;
            if (string.IsNullOrEmpty(prefix))
                    prefix = "DEFAULT";

            result.AddNamespace(prefix, localNamespace.Value);
        }
    }

    return result;
}

Просто обратите внимание на случай пространства имен по умолчанию. Я переопределил пространство имен по умолчанию как префикс "ПО УМОЛЧАНИЮ", потому что у меня возникли проблемы при создании SelectSingleNode с использованием вышеприведенного возвращаемого диспетчера пространства имен при запросе пространства имен по умолчанию. Я был моим помощником. Надеюсь, что это поможет

Ответ 2

Спасибо за ваш быстрый ответ...

Я думаю, что версия .Net, которую вы используете, должна быть последней. Я использую .Net framework 1.1... довольно старый:(..

К тому времени, у меня есть некоторый пример кода, подобный этому.. для той же цели...

XmlNodeList _xmlNameSpaceList =  _xmlDocument.SelectNodes(@"//namespace::*[not(. = ../../namespace::*)]");

            _xmlNSmgr = new XmlNamespaceManager(_xmlDocument.NameTable);        

            foreach(XmlNode nsNode in _xmlNameSpaceList)
            {
                _xmlNSmgr.AddNamespace(nsNode.LocalName,nsNode.Value);
            }

Любой комментарий будет оценен, чтобы добавить знания в мой KB... Благодаря

Ответ 3

Ваша основная проблема получения пространств имен из XmlDocument может быть решена путем простого извлечения NameTable XmlDocument и создания XmlNameSpaceManager из него.

Однако, если вы хотите перечислить пространства имен для какой-либо другой цели, вы должны проверить метод GetNamespacesInScope, открытый классом XmlNameSpaceManager, а также класс XPathNavigator.

При использовании XmlDocument вы можете получить XmlNamespaceManager с помощью следующего кода:

//Instantiate an XmlDocument object.
XmlDocument xmldoc = new XmlDocument();

//Load XML file into the XmlDocument object. 
xmldoc.Load("C:\\myFile.xml");

//Instantiate an XmlNamespaceManager object. 
XmlNamespaceManager nsMgr = new XmlNamespaceManager(xmldoc.NameTable);

// Retrieve the namespaces into a Generic dictionary with string keys.
IDictionary<string, string> dic = nsMgr.GetNamespacesInScope(XmlNamespaceScope.All);

// Iterate through the dictionary.

...

В этой статье Скотт Гензельман предлагает способ использовать этот метод для перечисления всех пространств имен в документе с помощью XPathNavigator и использования LINQ моста.

Ответ 4

Ruchita опубликовала рабочее решение для XmlDocument. Но я хотел сделать то же самое с XDocument. Вот то же самое с XDocument:

var xml = XDocument.Load(filename);
var xmlNameSpaceList = ((IEnumerable)xml.XPathEvaluate(@"//namespace::*[not(. = ../../namespace::*)]")).Cast<XAttribute>();
var xmlNSmgr = new XmlNamespaceManager(new NameTable());
foreach (var nsNode in xmlNameSpaceList)
{
    xmlNSmgr.AddNamespace(nsNode.Name.LocalName, nsNode.Value);
}

Теперь вы можете использовать XPath с пространствами имен, например. xml.XPathEvaluate("//test:p", xmlNSmgr).

Ответ 5

Если вы ищете быстрый способ избежать проблемы с пространством имен, разделите определения пространства имен из Xml через RegEx, прежде чем вы выполните XmlDocument.LoadXml(bla). Я делаю это при анализе живых страниц XHTML. Занимает время загрузки XmlDoc с 15 секунд до 0,15 секунды и делает это так, что мне не нужно префикс my xpaths.