Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Namespace-s, XPath, distinct & all this JAZZ... / 9 сообщений из 9, страница 1 из 1
25.11.2005, 13:25
    #33399918
qu-qu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Namespace-s, XPath, distinct & all this JAZZ...
Вдогонку...

Не люблю я этого "хард-кодирования", просто жуть...
А в приведенном выше примере (не от хорошей жизни, понимаю, а для повышения "наглядности") - пространства имен для <?mso-application progid="Excel.Sheet"?> надо было знать заранее, да запихивать их в XmlNamespaceManager явным образом "ручками"...

В результате недолгих раздумий - родился следующий код, демонстрирующий возможности "автоматического" добавления нужных Namespace -s для конкретного документа.

Но, как обычно это бывает - недолгие раздумия порождают неадекватные решения, так и здесь - существует некоторая "неоптимальность" или "незаконченность" решения, заключающаяся в том, что:
либо мы ограничиваемся набором Namespace -s из корневого элемента документа (и не имеем оверхеда);

либо получаем весь доступный набор Namespace -s из всего докумена, но при этом - бегаем "лишними" проходами цикла по всем узлам, имеющим в своем названии Namespace .

Отсюда вопрос: можно ли написать XPath -запрос к оси //namespace::* так, чтобы вернулся уникальный набор узлов (некий аналог distinct в SQL )?
(что-то у меня сходу не получилось)

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Xml.XPath;

public class Script
{
  public static string PrintError(Exception e, string errStr){

    if(e == null)
      return errStr;
    else
      return PrintError(e.InnerException, errStr + e.GetType().ToString() + "\r\n" + e.Message );
  }

	public static void Main(string[] args)
	{
     XmlDocument _doc = new XmlDocument();
     XmlNamespaceManager _nsMgr = new XmlNamespaceManager(_doc.NameTable);
     XmlNodeList _nodes;

     try
     {
       string _xml =
       @"<root xmlns='urn:default-ns-without-name' xmlns:ns1='urn:explicit-ns-with-name-ns1' xmlns:ns2='urn:explicit-ns-with-name-ns2'>
            <myTag1 myAttr='qu-qu1'>
              <ns1:myTag1.1 ns1:myAttr1.1='qu-qu1.1' ns2:myAttr2.1='qu-qu1.2'>
              </ns1:myTag1.1>
            </myTag1>
            <myTag2 myAttr='qu-qu2'>
              <ns2:myTag2.1 ns1:myAttr1.1='qu-qu2.1' ns2:myAttr2.1='qu-qu2.2'>
              </ns2:myTag2.1>
            </myTag2>
            <myTag3 xmlns:ns3='urn:inline-ns-with-name-ns3' myAttr='qu-qu3'>
              <ns3:myTag3.1 ns3:myAttr1.1='qu-qu3.1'>
              </ns3:myTag3.1>
            </myTag3>
         </root>";
       _doc.LoadXml(_xml);

       Console.WriteLine("Смотрим, что творится с добавлением в XmlNamespaceManager:");
       Console.WriteLine("(пока все достаточно лаконично)");
       foreach (XmlNode _ns in _doc.DocumentElement.SelectNodes("namespace::*[local-name(.) != 'xml' and local-name(.) != '']"))
       {
         _nsMgr.AddNamespace(_ns.LocalName, _ns.Value);
				  Console.WriteLine("{0}: {1}", _ns.LocalName, _ns.Value);
       }

           Console.WriteLine("сначала пробуем искать узлы без пространств имен (т.е. по-умолчанию).");
       _nodes = _doc.SelectNodes("//@myAttr", _nsMgr);
       foreach(XmlNode _node in _nodes)
         Console.WriteLine(_node.OuterXml + " NamespaceURI: " + _node.NamespaceURI);
           Console.WriteLine("теперь пробуем искать узлы с пространствами имен заданными в главном элементе.");
       _nodes = _doc.SelectNodes("//@ns1:myAttr1.1|//@ns2:myAttr2.1", _nsMgr);
       foreach(XmlNode _node in _nodes)
         Console.WriteLine(_node.OuterXml + " NamespaceURI: " + _node.NamespaceURI);
           Console.WriteLine("теперь пробуем искать узлы с пространствами имен заданными внутри документа.");
       _nodes = _doc.SelectNodes("//ns3:myTag3.1/@ns3:myAttr1.1", _nsMgr);
       foreach(XmlNode _node in _nodes)
         Console.WriteLine(_node.OuterXml + " NamespaceURI: " + _node.NamespaceURI);

     }catch(System.Xml.Xsl.XsltException xslte){
       Console.WriteLine("ERROR: XPath error occured while querying the document: " + PrintError(xslte, null));
        try {
           Console.WriteLine("теперь добавляем все пространства имен из всего документа (с многочисленными повторениями).");
           Console.WriteLine("Смотрим, что творится с добавлением в XmlNamespaceManager:");
           Console.WriteLine("(тут как-то лаконичностью и не пахнет)");
         foreach (XmlNode _ns in _doc.DocumentElement.SelectNodes("//namespace::*[local-name(.) != 'xml' and local-name(.) != '']"))
         {
           _nsMgr.AddNamespace(_ns.LocalName, _ns.Value);
  				  Console.WriteLine("{0}: {1}", _ns.LocalName, _ns.Value);
         }
           Console.WriteLine("теперь снова пробуем искать узлы с пространствами имен заданными внутри документа.");
           _nodes = _doc.SelectNodes("//ns3:myTag3.1/@ns3:myAttr1.1", _nsMgr);
         foreach(XmlNode _node in _nodes)
           Console.WriteLine(_node.OuterXml + " NamespaceURI: " + _node.NamespaceURI);

           Console.WriteLine("А вот и недостающее пространство имен подкатилось...");
           Console.WriteLine("Хотя, к слову сказать, XmlNamespaceManager лишего-то и не взял:");
           IEnumerator _en = _nsMgr.GetEnumerator();
           while (_en.MoveNext())
           {
              Console.WriteLine(_en.Current);
           }
           Console.WriteLine("Но, все равно, как-то - \"неаккуратненько\"... :-)");
        }catch(Exception e){
           Console.WriteLine("UNEXPECTED ERROR: " + PrintError(e, null));
        }
     }catch(XmlException xmle){
       Console.WriteLine("ERROR: XML Parse error occured because " + PrintError(xmle, null));
     }catch(XPathException xpath){
       Console.WriteLine("ERROR: The following error occured while querying the document: " + PrintError(xpath, null));
     }catch(Exception e){
       Console.WriteLine("UNEXPECTED ERROR: " + PrintError(e, null));
     }
	}
}
...
Рейтинг: 0 / 0
25.11.2005, 13:54
    #33400011
maXmo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Namespace-s, XPath, distinct & all this JAZZ...
эээ... а какой смысл автоматически добавлять (я так понял, заранее неизвестные) пространства имён? Чтобы работать с документом неизвестной структуры?
------------------
- А как в Интеpнете pаботать? - Сначала нужно узнать, что вам нужно rtfm
...
Рейтинг: 0 / 0
25.11.2005, 14:22
    #33400131
jimmers
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Namespace-s, XPath, distinct & all this JAZZ...
В XPath 2.0 есть такой синтаксис:

Код: plaintext
distinct-values(//namespace::*)

Правда я не вижу смысла в таком универсальном подходе по причине того, что всё равно для работы с XML документом придётся забиваться на определённую его структуру. В частности, использовать те же LocalNames в запросах.

С уважением,
Мартин Рахманов
http://jimmers.russia.webmatrixhosting.net/
...
Рейтинг: 0 / 0
25.11.2005, 16:01
    #33400576
qu-qu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Namespace-s, XPath, distinct & all this JAZZ...
maXmoэээ... а какой смысл автоматически добавлять (я так понял, заранее неизвестные) пространства имён?


Ну-у-у-у, писал же я в начале своего поста - "не люблю хард-кодирование"...
Оно, конечно, Copy-Paste - прогрессивный способ написания кода, но иногда больно "бьет" по затылку граблями, которые не сразу-то и заметишь...
(это я к тому, что когда в заголовке документа 5-7-10 пространств имен, как у того же сохраненного ADODB.Recordset -a, например - то заколебешься "пыль глотать" прописывая их всех в XmlNamespaceManager ради одного запроса к одной конкретной <z:row/> )

maXmo
Чтобы работать с документом неизвестной структуры?

Не-е-е-е, на такое я не замахиваюсь, как говорят в рекламе - "это фантастика..."

jimmers
... я не вижу смысла в таком универсальном подходе...
...использовать те же LocalNames в запросах...

Так ведь, ради этого, собственно говоря, и весь сыр-бор затевался...
Когда реальный документ имеет структуру узлов с Namespace -s, то - хоть ты тресни, а без указания LocalNames в запросах ничего из этого документа выбрать нельзя:
типа, для моего примера - "//@myAttr1.1" вернет фигу с маслом...
Но даже, если я "глазами вижу" (в доступной обозрению "известной" структуре документа), что запрос надо переписать так:
"//@ns1:myAttr1.1" - то спрашивается: зачем для составления запроса и (главное!) получения правильного результата мне знать, что же именно скрывается под таким "гордым" пространством имен как "ns1" , и ладно бы "знать", так еще и в явном виде прописывать это в несчастный XmlNamespaceManager , без которого мой "правильный" вариант запроса все равно работать не будет...

Пусть уж это компьютер делает на пару с .NET Framework (у них "мозги железные", лишний раз пару тысяч циклов пробежать для довольно большого документа набитого префиксами Namespace -s - не переломятся).
З.Ы. это я так, "для красного словца"...

З.З.Ы. а насчет XPath 2.0 - он реализован сейчас где-нить у мелко-мягких?
...
Рейтинг: 0 / 0
25.11.2005, 19:06
    #33401018
maXmo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Namespace-s, XPath, distinct & all this JAZZ...
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
...
<Worksheet ss:Name="Sheet1">

вопрос: как получить атрибут @ss:Name элемента Worksheet? Как определить, из какого из четырёх указанных пространств имён он взят. Не зная самих пространств имён. Пвой метод может, например, сделать так: виделить элементы из четвёртого пространства имён (в порядке определения пространств имён в корневом элементе). Но он не может выделить элементы из пространства имён экселя (определено третьим по счёту).
------------------
- А как в Интеpнете pаботать? - Сначала нужно узнать, что вам нужно rtfm
...
Рейтинг: 0 / 0
25.11.2005, 19:09
    #33401021
maXmo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Namespace-s, XPath, distinct & all this JAZZ...
хард-кодирование пространств имён эквивалентно хард-кодированию IID (идентификаторов интерфейса). Их именно для этого и делали. Другое пространство имён - другая структура документа. Если ты знаешь структуру документа, то ты знаешь и пространства имён, которые в нём используются.
------------------
- А как в Интеpнете pаботать? - Сначала нужно узнать, что вам нужно rtfm
...
Рейтинг: 0 / 0
28.11.2005, 11:29
    #33402886
qu-qu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Namespace-s, XPath, distinct & all this JAZZ...
maXmo<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:o="urn:schemas-microsoft-com:office:office"
xmlns:x="urn:schemas-microsoft-com:office:excel"
xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
xmlns:html="http://www.w3.org/TR/REC-html40">
...
<Worksheet ss:Name="Sheet1">

вопрос: как получить атрибут @ss:Name элемента Worksheet? Как определить, из какого из четырёх указанных пространств имён он взят. Не зная самих пространств имён. Пвой метод может, например, сделать так: виделить элементы из четвёртого пространства имён (в порядке определения пространств имён в корневом элементе). Но он не может выделить элементы из пространства имён экселя (определено третьим по счёту).

Вот, вижу, что человек (вроде, неглупый) пытался что-то понять, а то, что понял - не вижу...
Какая разница для XmlNamespaceManager - каким по счету ("третьим", или "четвертым", или 25-м) определено "нужное ему" (а не мне, заметь) пространство имен в корневом элементе? Он берет их - ВСЕ (по-моему, это очевидно).

Другое дело, что примерчик ты подкинул, что называется "с закавыкой" - т.к. в сохраненном листе Экселя (для внимательных наблюдателей) 2 раза определяется одно и то же пространство имен "urn:schemas-microsoft-com:office:spreadsheet" (один раз как "по-умолчанию", без алиаса, а второй раз - с алиасом "ss" ). На этом-то XPath-запросы и "клинит", т.е. - насколько я понимаю, все элементы из пространства имен "по-умолчанию" надо запрашивать с префиксом "ss" (невелика забота, раз уж "атрибут @ss:Name элемента Worksheet" все равно требует этого префикса).

На всяк. случай я сделал примерчик, где "Пвой" метод "может" ровно столько же, сколько и мой (пока не напишешь правильный префикс в XPath-запросе):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
using System;
using System.Collections;
using System.IO;
using System.Xml;
using System.Xml.XPath;

public class Script
{
  public static XmlNamespaceManager GetmaXmoNsMgr(XmlDocument doc)
  {
     XmlNamespaceManager _nsMgr = new XmlNamespaceManager(doc.NameTable);
     try
     {
         _nsMgr.AddNamespace("", "urn:schemas-microsoft-com:office:spreadsheet");
         _nsMgr.AddNamespace("ss", "urn:schemas-microsoft-com:office:spreadsheet");
     }catch(Exception e){
       Console.WriteLine("GetmaXmoNsMgr Exception's occured: " + PrintError(e, null));
     }
     return _nsMgr;
  }

  public static XmlNamespaceManager GetNsMgr(XmlDocument doc)
  {
     XmlNamespaceManager _nsMgr = new XmlNamespaceManager(doc.NameTable);
     try
     {
       foreach (XmlNode _ns in doc.DocumentElement.SelectNodes("namespace::*[local-name(.) != '']"))
       {
         _nsMgr.AddNamespace(_ns.LocalName, _ns.Value);
			 }
     }catch(Exception e){
       Console.WriteLine("GetNsMgr Exception's occured: " + PrintError(e, null));
     }
     return _nsMgr;
  }

  public static XmlNodeList SelectQNodes(XmlDocument doc, string xpath)
  {
     XmlNodeList _nodes = null;
     try
     {
       _nodes = doc.SelectNodes(xpath, GetNsMgr(doc));
     }catch(Exception e){
       Console.WriteLine("SelectQNodes Exception's occured: " + PrintError(e, null));
     }
     return _nodes;
  }

  public static string PrintError(Exception e, string errStr){

    if(e == null)
      return errStr;
    else
      return PrintError(e.InnerException, errStr + e.GetType().ToString() + "\r\n" + e.Message );
  }

	public static void Main(string[] args)
	{
     XmlDocument _doc = new XmlDocument();

     try
     {
       string _xml =
       @"<Workbook xmlns='urn:schemas-microsoft-com:office:spreadsheet'
                xmlns:ss='urn:schemas-microsoft-com:office:spreadsheet'
          xmlns:o='urn:schemas-microsoft-com:office:office'
          xmlns:x='urn:schemas-microsoft-com:office:excel'
          xmlns:html='http://www.w3.org/TR/REC-html40'>
          <Worksheet ss:Name='Sheet1'/>
        </Workbook>";
       _doc.LoadXml(_xml);

       XmlNodeList _nodes = SelectQNodes( _doc,"//Worksheet/@ss:Name");
       foreach(XmlNode _node in _nodes)
         Console.WriteLine(_node.OuterXml + " NamespaceURI 0.0: " + _node.NamespaceURI);
       _nodes = _doc.SelectNodes("//Worksheet/@ss:Name", GetmaXmoNsMgr(_doc));
       foreach(XmlNode _node in _nodes)
         Console.WriteLine(_node.OuterXml + " NamespaceURI 0.1: " + _node.NamespaceURI);

       _nodes = SelectQNodes( _doc,"//Worksheet/@Name");
       foreach(XmlNode _node in _nodes)
         Console.WriteLine(_node.OuterXml + " NamespaceURI 1.0:" + _node.NamespaceURI);
       _nodes = _doc.SelectNodes("//Worksheet/@Name", GetmaXmoNsMgr(_doc));
       foreach(XmlNode _node in _nodes)
         Console.WriteLine(_node.OuterXml + " NamespaceURI 1.1: " + _node.NamespaceURI);

       _nodes = SelectQNodes( _doc,"//ss:Worksheet/@ss:Name");
       foreach(XmlNode _node in _nodes)
         Console.WriteLine(_node.OuterXml + " NamespaceURI 2.0: " + _node.NamespaceURI);
       _nodes = _doc.SelectNodes("//ss:Worksheet/@ss:Name", GetmaXmoNsMgr(_doc));
       foreach(XmlNode _node in _nodes)
         Console.WriteLine(_node.OuterXml + " NamespaceURI 2.1: " + _node.NamespaceURI);

     }catch(Exception e){
       Console.WriteLine("Main Exception's occured: " + PrintError(e, null));
     }
	}
}
...
Рейтинг: 0 / 0
28.11.2005, 18:43
    #33404352
maXmo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Namespace-s, XPath, distinct & all this JAZZ...
qu-quНа всяк. случай я сделал примерчик, где "Пвой" метод "может" ровно столько же, сколько и мой (пока не напишешь правильный префикс в XPath-запросе)ну приехали... это ли не хард-кодирование? Хардкодить название префикса вместо самого пространства имён??? Ты это предлагаешь?
...
Рейтинг: 0 / 0
28.11.2005, 19:25
    #33404412
qu-qu
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Namespace-s, XPath, distinct & all this JAZZ...
maXmo...ну приехали... это ли не хард-кодирование? Хардкодить название префикса вместо самого пространства имён??? Ты это предлагаешь?

Я ничего не предлагаю...
Я знаю твердо одну вещь, что пока не напишешь в XPath-запросе правильное название префикса пространства имен - ничего он тебе (и мне, кстати) не выберет. А если напишешь "правильное", то он без XmlNamespaceManager-а скажет тебе, что не знает такого префикса...
А XmlNamespaceManager не хочет ничего узнавать про префиксы без самих URI...
Так вот, мне эти URI - нафиг не нужны (в большинстве случаев), а тебе, если хочется понабивать ручками их в методе XmlNamespaceManager.AddNamespace(...) - да хоть обнабивайся.

Не собираюсь больше продолжать эту дискуссию только ради оставления за собой "последнего слова"... можешь придумать еще какой-нить "аргумент" и назвать его - "хард-кодирование".
...
Рейтинг: 0 / 0
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / Namespace-s, XPath, distinct & all this JAZZ... / 9 сообщений из 9, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]