|
v7: как узнать префиксы пространства имен по namespaceURI (MSXML.DOMDocument) | ☑ | ||
---|---|---|---|---|
0
gugolovski
04.06.21
✎
08:03
|
есть некий xlm документ.
namespaceURI неизменный, а префиксы меняются из раза в раз Например: 1) <?xml version="1.0" encoding="UTF-8" ?> <ns:Documents h:table xmlns:h="http://www.w3.org/TR/html4/">... Здесь prefix = h namespaceURI = "http://www.w3.org/TR/html4/" 2)<?xml version="1.0" encoding="UTF-8" ?> <ns:Documents h:table xmlns:a="http://www.w3.org/TR/html4/">... prefix = а namespaceURI = "http://www.w3.org/TR/html4/" загружаем документ.. xlm=СоздатьОбъект("MSXML.DOMDocument"); xlm.load(файл); Можно ли по namespaceURI узнать префикс текущего пространства имен? |
|||
1
Василий Алибабаевич
04.06.21
✎
08:16
|
(0) Вот здесь : https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ms760428(v=vs.85) есть пример на жабе. И пишут что оно есть просто свойство конкретного элемента.
|
|||
2
Василий Алибабаевич
04.06.21
✎
08:17
|
+ (1) В примере получают все ПространстваИмен объявленные в схеме по адресу ПространстваИменУРИ.
|
|||
3
MWWRuza
гуру
04.06.21
✎
14:58
|
Это по ходу, задача автора топика - ТТНки ЕГАИС... Некоторые поставщики-извращенцы, любят такое делать. Схемы позволяют... Каких только префиксов иногда не придумывают :-)
Я когда с таким столкнулся, стал придумывать, как с этим бороться. Соорудил, некое решение, не уверен, что оптимальное, но работает... Из УТМ получаю таблицу "стандартных префиксов"(из схем), и парсинг новой ТТН, начинаю с чтения заголовка и сопоставления в таблице стандартных префиксов, префиксов полученных из заголовков стандартным префиксам. Сопоставление делаю по namespaceURI. Таблицу эту храню в переменной на время парсинга этой ХМЛки... Там, где мне нужно получить нужный текущий "префикс от извращенцев", получаю его функцией из этой таблицы ТекПрефикс([имя стандартного префикса])... Имя стандартного префикса, это то имя, которое в данном месте ожидалось, согласно описанию УТМа. Еще раз! Не утверждаю, что такая схема оптимальна, и нельзя сделать что-то проще, но... Сделано давно, успешо работает... Варианты парсить ХМЛ как текст, просто по именам тегов - не рассматриваю, MSXML через DOM как-то нравится больше... А там, вроде, без префиксов не обойтись(хотя, могу и ошибаться). Единственное, при переходе на УТМ4, пришлось поправить функцию получения таблицы "стандартных префиксов", т.к., схемы документов там по другому хранятся... И вообще, такое ощущение, что УТМ4 писался совсем другой командой разработчиков "с нуля", там много чего по другому, чем в УТМ 1, 2 и 3, чего можно было и не трогать... Нооо... Что есть, то есть. |
|||
4
gugolovski
07.06.21
✎
09:04
|
(3) Да все верно ТТН-ки.) Завис с этими префииксами. Не могу получить их. Не знаю какой командой их извлекать
Например, xlm=СоздатьОбъект("MSXML.DOMDocument"); xlm.load(файл); коллекцияNS = xlm.namespaces; Для сч = 0 По коллекцияNS.length-1 Цикл Сообщить(коллекцияNS.namespaceURI(сч)); КонецЦикла; Здесь получаю URI: http://www.w3.org/TR/html4/, а как получить префикс? |
|||
5
zenik
07.06.21
✎
09:21
|
А зачем префиксы то?
xmldoc = СоздатьОбъект("Msxml2.DOMDocument.6.0"); xmldoc.async = 0; xmldoc.load(Файл); Для n = 0 По xmldoc.childnodes.length - 1 Цикл ChildNodes = xmldoc.childnodes.item(n); Сообщить(ChildNodes.BaseName); КонецЦикла; ChildNodes.BaseName - будет без всяких префиксов... |
|||
6
MWWRuza
гуру
07.06.21
✎
09:21
|
Еще раз предупреждаю - не претендую на оптимальность кода, критиковать бесполезно, делал давно, и с появлением УТМ4 дописывал по методу "латания дыр". Но, работает.
И, это не весь код, могут быть ссылки на какие-то функции, которых нет в этом фрагменте, но, общий принцип - думаю поможет понять. Если что-то не понятно - пишите, дополню... Функция ПолучитьТзСтандартныхПрефиксов() ТЗ = СоздатьОбъект("ТаблицаЗначений"); ТЗ.НоваяКолонка("СтПреф"); ТЗ.НоваяКолонка("URL"); ОП = глЗначениеПоУмолчанию("ОсновнаяФирма").ЮрЛицо; УТМ_URL = СокрЛП(ОП.УТМ_URL); СЗ = ПолучитьВерсиюИ_ЕГАИС_ID(УТМ_URL); Версия = Лев(СЗ.Получить("Версия"), 1); Если Версия = "4" Тогда URL = УТМ_URL + "api/schema/WB_DOC_SINGLE_01.xsd"; // URL Схемы документов XSD из УТМ 4 Иначе URL = УТМ_URL + "info/xsdWholesale/WEGAIS/WB_DOC_SINGLE_01.xsd"; // URL Схемы документов XSD КонецЕсли; Скрипт = СоздатьОбъект("MSScriptControl.ScriptControl"); Скрипт.language="vbscript"; Это = Скрипт.Eval("this"); WinHttp = СоздатьОбъект("WinHttp.WinHttpRequest.5.1"); Скрипт.AddObject("WinHttp",WinHttp); WinHttp.Open("GET", URL, 0); Попытка WinHttp.Send(); Исключение Сообщить("Служба УТМ не запущена, невозможно получить список входящих документов!"); Возврат ""; КонецПопытки; Если WinHTTP.Status<>200 Тогда Предупреждение("Не удалось загрузить документ. Возможно он удалён или служба УТМ не запущена."); Возврат ""; КонецЕсли; Стрим = СоздатьОбъект("ADODB.Stream"); Стрим.Mode = 3; Стрим.Type = 1; Стрим.Open(); Скрипт.AddObject("Stream",Стрим); XML_DOM = CreateObject("MSXML2.DOMDocument.6.0"); Скрипт.Eval("Stream.Write(WinHttp.responseBody)"); Стрим.Position = 0; Стрим.Type = 2; Стрим.Charset = "utf-8"; Ответ = Стрим.ReadText(); Стрим.Close(); Если Версия = "4" Тогда СтрСхем = Ответ; Иначе НачТела = Найти(Ответ,"<pre>"); Ответ = Сред(Ответ,НачТела); КонТела = Найти(Ответ,"</pre>") + 5; Ответ = Лев(Ответ,КонТела); XML_DOM.LoadXML(Ответ); NamRootNodSchem = XML_DOM.DocumentElement.selectSingleNode("/*").NodeName; СтрСхем = XML_DOM.selectSingleNode(NamRootNodSchem).text; КонецЕсли; Пока Найти(СтрСхем,"xmlns:") > 0 Цикл ОстСтр = Сред(СтрСхем,Найти(СтрСхем,"xmlns:") + 6); НачАдреса = Найти(ОстСтр,"="); ТекПреф = Лев(ОстСтр,НачАдреса - 1); ТекПреф = СтрЗаменить(ТекПреф,"2",""); ТекПреф = СтрЗаменить(ТекПреф,"3",""); ОстСтр = Сред(ОстСтр,НачАдреса + 2); КонАдреса = Найти(ОстСтр,"""") - 1; ТекАдрес = Сред(ОстСтр,1,КонАдреса); СтрСхем = ОстСтр; ТЗ.НоваяСтрока(); ТЗ.СтПреф = ТекПреф; ТЗ.URL = ТекАдрес; КонецЦикла; ТЗ.Сортировать("СтПреф, URL"); Возврат ТЗ; КонецФункции Функция ТекПреф(СтПр) Экспорт ТекСтрСоот = ""; ТекПреф = ""; Если ТабПреф.НайтиЗначение(СтПр,ТекСтрСоот,"СтПреф") = 1 Тогда ТекПреф = ТабПреф.ПолучитьЗначение(ТекСтрСоот,"НовПреф"); КонецЕсли; Возврат ТекПреф; КонецФункции Процедура ЗаполнитьТабПростИмен(nod) // Рекурсивная процедура, пробегает по всему DOM и вытаскивает из него прециксы и URL_NS в ТЗ. ИмяПреф = nod.prefix; URL_NS = nod.namespaceURI; Если СокрЛП(ИмяПреф) <> "" Тогда ТабПреф.НоваяСтрока(); ТабПреф.НовПреф = ИмяПреф; ТабПреф.URL = URL_NS; ТабПреф.Сверт = 1; КонецЕсли; node = nod.childNodes; Ind = 0; Для Ind = 1 По node.Length Цикл ChildNod = node.item(ind - 1); ИмяПреф = ChildNod.prefix; URL_NS = ChildNod.namespaceURI; Если СокрЛП(ИмяПреф) <> "" Тогда ТабПреф.НоваяСтрока(); ТабПреф.НовПреф = ИмяПреф; ТабПреф.URL = URL_NS; ТабПреф.Сверт = 1; КонецЕсли; ЗаполнитьТабПростИмен(ChildNod); КонецЦикла; КонецПроцедуры |
|||
7
MWWRuza
гуру
07.06.21
✎
09:24
|
Во... В (6), как раз то, о чем я думал - надо вообще от префиксов избавиться при парсинге. Это намного оптимальнее. Надо будет попробовать... Только теперь, переделывать уже много, лень :-(
|
|||
8
gugolovski
07.06.21
✎
10:40
|
(6) как я понимаю в этом куске кода делается выборка из схем документов XSD: в таблицу значений прописываются пространства имен и префиксы данные разработчиками. а как выдергивать префиксы их ТТН полученные от поставщика?
|
|||
9
MWWRuza
гуру
07.06.21
✎
12:55
|
Вот: Процедура ЗаполнитьТабПростИмен(nod) // Рекурсивная процедура, пробегает по всему DOM и вытаскивает из него прециксы и URL_NS в ТЗ.
Это собираются все префиксы из текущей ХМЛки, которую парсите. Сами строки ХМЛ читаете например так: DocumentNode = XML_DOM.selectSingleNode("/" + ТекПреф("ns") + ":Documents/" + ТекПреф("ns") + ":Document").firstChild; В функции ТекПреф("ns") - "ns", это тот префикс который стандартный, заданный в схемах содержащихся в УТМ. Соответственно, "ns" будет заменен на тот префикс, который ему соответствует и находится на этом месте в реальной ХМЛ. PS Но, лучше, не идти по этому пути, а попытаться разобраться по методике как в (6) предложено... |
|||
10
victuan1
08.06.21
✎
05:58
|
(9) в (6) или (5) всё-таки?
|
|||
11
MWWRuza
гуру
08.06.21
✎
09:53
|
(10) Не понял вопрос... (9) был ответ на предыдущее, (8).
|
|||
12
trad
08.06.21
✎
10:17
|
(0) не надо узнавать "чужие" префиксы, надо работать со своими префиксами для пространств имен.
Используй xlm.setProperty("SelectionNamespaces", "xmlns:h='http://www.w3.org/TR/html4/'"); Вот тут "xmlns:h=" вместо h можешь сохранить любой из "чужих" или придумать свой префикс. И далее, в коде, обращаться к узлам всегда h:table (с применением, указанного в SelectionNamespaces, префикса) ps можно перечислить все употребимые в коде префиксы в xlm.setProperty("SelectionNamespaces", "xmlns:h='http://www.w3.org/TR/html4/' |xmlns:pr1='NS1' |xmlns:pr2='NS2' |... |"); |
|||
13
gugolovski
08.06.21
✎
13:45
|
(9) Мне понравился ваш метод с рекурсией - теперь знаю как обежать весь документ xml.
Но остановлюсь на варианте: (12) setProperty - очень просто, красиво, легко. Ребята, спасибо огромное) |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |