Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как найти нод, если не известен его неймспейс, Вопрос по XPath 
:(
    Опции темы
Naum
Дата 23.5.2007, 12:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 743
Регистрация: 7.9.2005
Где: Саратов, ул. Поса дского, 298

Репутация: 8
Всего: 15



Доброго всем времени суток. 
Собственно сабж.
Пример:
Код

XmlNamespaceManager namespaceManager = new XmlNamespaceManager(vendorResponse.OwnerDocument.NameTable);
namespaceManager.AddNamespace("rootNs", vendorResponse.NamespaceURI);
_airlines = ComposeTableOfCodes(vendorResponse.SelectNodes("//rootNs:Decode/rootNs:Airline", namespaceManager));
_airports = ComposeTableOfCodes(vendorResponse.SelectNodes("//rootNs:Decode/rootNs:Airport", namespaceManager));

Получается, чтобы найти элемент нужно знать, какой у него будет неймспейс smile , потому как у нода Decode неймспейс не обязательно будет такой же как и у корневого нода.
Товарищи мне тут подсказали чуть-чуть (а потом отпинали, типа отстань у самих работы полно smile), что такого XPath запроса не существует.  smile Но можно перебрать все неймспейсы в документе. Вот я и решил обратиться к форумчанам любимого форума.
Подскажите, плиз, как получить все неймспейсы в XmlDocument или XmlElement. Или другие способы, как найти нод, если не известен его неймспейс.

З.Ы. 1-й Фреймворк.  smile 

Это сообщение отредактировал(а) Naum - 23.5.2007, 12:23


--------------------
У нас всего два праздника Новый год и ТЯПница.
PM MAIL ICQ   Вверх
tol05
Дата 23.5.2007, 12:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



XmlElement.Prefix Property
XmlNode.Prefix Property
XmlDocument.Prefix Property

по-моему так. smile


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Naum
Дата 23.5.2007, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 743
Регистрация: 7.9.2005
Где: Саратов, ул. Поса дского, 298

Репутация: 8
Всего: 15



Цитата(tol05 @  23.5.2007,  13:27 Найти цитируемый пост)
XmlElement.Prefix

неймспейс данного элемента
Цитата(tol05 @  23.5.2007,  13:27 Найти цитируемый пост)
XmlNode.Prefix Property

неймспейс данного нода
Цитата(tol05 @  23.5.2007,  13:27 Найти цитируемый пост)
XmlDocument.Prefix

неймспейс корневого элемента документа

Мне же нужно получить все неймспейсы, которые есть в документе.
Например,
Код

<rootElement xmlns = 'rootNamespace'>
    <FirstChild xmlns = 'firstNamespace'>
    <!-- ................
    ....................-->
    </FirstChild>
    <SecondChild xmlns = 'secondNamespace'>
    <!-- ................
    ....................-->
    </SecondChild>
</rootElement>

Как мне получить все неймспейсы в документе, т.е. {"rootNamespace", "firstNamespace", "secondNamespace"}


--------------------
У нас всего два праздника Новый год и ТЯПница.
PM MAIL ICQ   Вверх
tol05
Дата 23.5.2007, 16:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



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


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Naum
Дата 23.5.2007, 19:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 743
Регистрация: 7.9.2005
Где: Саратов, ул. Поса дского, 298

Репутация: 8
Всего: 15



Цитата(tol05 @  23.5.2007,  17:44 Найти цитируемый пост)
рекурсивный цикл и условие для отбора.

Это понятно.  smile Но, ИМХО, это потеря в скорости(XML Очень большой). Элементов у него оч. много, а неймспейсов - максимум 3. Нафик тогда XPath?
Что мне кажется, что как-то это можно сделать через XmlDocument.NameTable, но пока не пойму как. :(



--------------------
У нас всего два праздника Новый год и ТЯПница.
PM MAIL ICQ   Вверх
tol05
Дата 23.5.2007, 19:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



вот пример через reader
Код

XmlTextReader reader = new XmlTextReader("myfile.xml");
XmlNamespaceManager nsmanager = new XmlNamespaceManager(reader.NameTable);
IDictionary<string, string> collection = nsmanager.GetNamespacesInScope(XmlNamespaceScope.All);


может и через документ можно?
Код

XmlNamespaceManager nsmanager = new XmlNamespaceManager(document.NameTable);
IDictionary<string, string> collection = nsmanager.GetNamespacesInScope(XmlNamespaceScope.All);



--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Naum
Дата 24.5.2007, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 743
Регистрация: 7.9.2005
Где: Саратов, ул. Поса дского, 298

Репутация: 8
Всего: 15



Пасиб. Но у меня 1-й фрэймворк. Там такого нет.


--------------------
У нас всего два праздника Новый год и ТЯПница.
PM MAIL ICQ   Вверх
tol05
Дата 24.5.2007, 12:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



чего нет? XmlNamespaceScope и GetNamespacesInScope?
Так возьми рефлектор и код сдери.
Код

public virtual IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
{
    int index = 0;
    switch (scope)
    {
        case XmlNamespaceScope.All: //это 0
            index = 2;
            break;

        case XmlNamespaceScope.ExcludeXml: //это 1
            index = 3;
            break;

        case XmlNamespaceScope.Local: //это 2
            index = this.lastDecl;
            while (this.nsdecls[index].scopeId == this.scopeId)
            {
                index--;
            }
            index++;
            break;
    }
    Dictionary<string, string> dictionary = new Dictionary<string, string>((this.lastDecl - index) + 1);
    while (index <= this.lastDecl)
    {
        string key = this.nsdecls[index].prefix;
        string uri = this.nsdecls[index].uri;
        if (uri != null)
        {
            if (((uri.Length > 0) || (key.Length > 0)) || (scope == XmlNamespaceScope.Local))
            {
                dictionary[key] = uri;
            }
            else
            {
                dictionary.Remove(key);
            }
        }
        index++;
    }
    return dictionary;
}


теперь есть.  smile 


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Naum
Дата 24.5.2007, 13:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 743
Регистрация: 7.9.2005
Где: Саратов, ул. Поса дского, 298

Репутация: 8
Всего: 15



smile Простой ты. Что ж мне теперь весь XmlNamespaceManager переписывать. ;) nsdecls например private. 


--------------------
У нас всего два праздника Новый год и ТЯПница.
PM MAIL ICQ   Вверх
tol05
Дата 24.5.2007, 13:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Во-первых. А почему бы и нет? Код уже написан и отлажен, просто лишнее выбросишь. Или ты XmlNamespaceManager-велосипед изобретать будешь? smile Чуваки поняли, что в 1-ой версии народ парился, вот и дописали. Ты сейчас по этому же пути идешь.
Во-вторых. Зачем переписывать XmlNamespaceManager? Я тебе функцию кинул, вот и вставь ее влюбой из своих классов. При вызове - передавай XmlDocument.NameTable, ну а внутри... поставь вместо nsdecls свой массив, да и заполняй его, так же, как nsdecls в конструкторе XmlNamespaceManager заполняется  
Код

public XmlNamespaceManager(XmlNameTable nameTable)
{
    this.nameTable = nameTable;
    this.xml = nameTable.Add("xml");
    this.xmlNs = nameTable.Add("xmlns");
    this.nsdecls = new NamespaceDeclaration[8];
    string prefix = nameTable.Add(string.Empty);
    this.nsdecls[0].Set(prefix, prefix, -1, -1);
    this.nsdecls[1].Set(this.xmlNs, nameTable.Add("http://www.w3.org/2000/xmlns/"), -1, -1);
    this.nsdecls[2].Set(this.xml, nameTable.Add("http://www.w3.org/XML/1998/namespace"), 0, -1);
    this.lastDecl = 2;
    this.scopeId = 1;
}

Это просто вариант действующей реализации твоей мечты!  smile 
Ну а код, что я запостил - это уже не их код, и даже не мой... Это твой код! 
Вот и делай с ним что хочешь.  smile 
Цитата(Naum @  23.5.2007,  19:21 Найти цитируемый пост)
мне кажется, что как-то это можно сделать через XmlDocument.NameTable





--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
Naum
Дата 24.5.2007, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 743
Регистрация: 7.9.2005
Где: Саратов, ул. Поса дского, 298

Репутация: 8
Всего: 15



 smile 
tol05, спасибо за помощь. Я уже тоже полазил в Xml через рефлектор. Получается можно только рекурсивно добавить все неймспейсы. :(
В конструкторе никаких неймспейсов в НСМенеджер не добавляется. То есть пока я их ручками не добавлю, там их и не будет. 
По идее все правильно. Ведь в нормальных Xml-документах все неймспейсы и, соответсвующие им, префиксы объявляются в корневом элементе, а у остальных элементов неймспейс определяется с помощью префикса. Это мне просто кривой Xml приходит. :(


--------------------
У нас всего два праздника Новый год и ТЯПница.
PM MAIL ICQ   Вверх
tol05
Дата 24.5.2007, 17:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1632
Регистрация: 21.12.2006
Где: Харьков

Репутация: 63
Всего: 170



Ну чтогда действительно, возьми какой-нибудь из reader-ов и парси вручную. В конце концов, XmlNamespaceManager, XmlDocument так же инфу получают (внутри себя). Не с потолка же они инфу берут? smile 

Те же reader-ы. Например
Код

public XmlTextReader (TextReader input)

или, ф-ция XmlDocument.Load(string name) - inside smile
Код

public virtual void Load(string filename)
{
    XmlTextReader reader = this.SetupReader(new XmlTextReader(filename, this.NameTable));
    try
    {
        this.Load(reader);
    }
    finally
    {
        reader.Close();
    }
}

где XmlTextReader reader  - см. выше


Да и быстрее будет - лишнего инициализировать не будешь.


--------------------
На хорошей работе и сны хорошие снятся.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0855 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.