|
v7: Запутался с формированием XML, подскажите, кто знает... | ☑ | ||
---|---|---|---|---|
0
MWWRuza
гуру
08.10.19
✎
03:08
|
Добрый день!
Формирую XML, с помощью "MSXML2.DOMDocument.6.0" Обычное дело, таких XML много где у ченя формируется, все просто и понятно. Но!!! Тут понадобилось сформировать немного "нестандартную" XMLку... В чем отличие - обычно, или есть явно объявленные пространства имен и префиксы, или их нет. Тут - у родительских узлов есть префиксы, а у последнего дочернего - нет. Вот пример, как должно выглядеть: <?xml version="1.0" encoding="UTF-8"?> -<ns:Documents xmlns:ns="http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01" xmlns="http://fsrar.ru/WEGAIS/QueryFilter" Version="1.0"> -<ns:Owner> <ns:FSRAR_ID>02000012****</ns:FSRAR_ID> </ns:Owner> -<ns:Document> -<ns:QueryFilter> <bc>101200026723**********************</bc> <bc>101200026723**********************</bc> </ns:QueryFilter> </ns:Document> </ns:Documents> У меня же, получается вот так: <?xml version="1.0" encoding="UTF-8"?> -<ns:Documents xmlns:ns="http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01" xmlns="http://fsrar.ru/WEGAIS/QueryFilter" Version="1.0"> -<ns:Owner> <ns:FSRAR_ID>02000012****</ns:FSRAR_ID> </ns:Owner> -<ns:Document> -<ns:QueryFilter> <bc xmlns="">1012000267231110180*************</bc> <bc xmlns="">1012000267231710180*************</bc> </ns:QueryFilter> </ns:Document> </ns:Documents> (сокращено и забито звездочками для наглядности) Проблема в том, что в каждой строке тега "bc" добавляется атрибут пространства имен по умолчанию: " xmlns="""... В таком виде, программа, для которой формируется эта XMLка, ее не глотает, выдает ошибку... Если в "блокноте" заменить во всем файле " xmlns=""" на "", то все работает. Как избавится от этого лишнего атрибута? Нет, я конечно понимаю, что можно пробежаться программно по тексту XML и тупо заменить " xmlns=""" на "", не проблема... Но, это как-то не красиво. Как это сделать при формировании DOM - ??? Ведь наверняка как-то можно? Вот фрагмент кода, как я это все формирую: XML_DOM = CreateObject("MSXML2.DOMDocument.6.0"); XML_HELPER = CreateObject("Msxml2.MXNamespaceManager.6.0"); XML_HELPER.declarePrefix("ns", "http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01"); Header = XML_DOM.createProcessingInstruction("xml", "version=""1.0"" encoding=""UTF-8"" standalone=""no"""); XML_DOM.appendChild(Header); XML_ROOT = ДобавитьУзел(XML_DOM, XML_HELPER, XML_DOM, "Documents", "ns"); ДобавитьАттрибут(XML_DOM, XML_ROOT, "Version", "1.0"); ДобавитьАттрибут(XML_DOM, XML_ROOT, "xmlns", "http://fsrar.ru/WEGAIS/QueryFilter"); // Version="1.0""); XML_OWNER = ДобавитьУзел(XML_DOM, XML_HELPER, XML_ROOT, "Owner", "ns"); XML_FSRAR_ID = ДобавитьУзел(XML_DOM, XML_HELPER, XML_OWNER, "FSRAR_ID", "ns"); ДобавитьТекст(XML_DOM, XML_FSRAR_ID, ФСРАР_ID); XML_DOCUMENT = ДобавитьУзел(XML_DOM, XML_HELPER, XML_ROOT, "Document", "ns"); XML_QF = ДобавитьУзел(XML_DOM, XML_HELPER, XML_DOCUMENT, "QueryFilter", "ns"); Для Сч = 1 По ТЗ.КоличествоСтрок() Цикл // Отладка Если Сч = 101 Тогда Прервать; КонецЕсли; // XML_BC = ДобавитьУзел(XML_DOM, XML_HELPER, XML_QF, "bc",); // XML_DOM. XML_BC = XML_DOM.createNode(1,"bc",); // XML_BC = XML_DOM.createNode(1,"bc", ""); // ДобавитьАттрибут(XML_DOM, XML_BC, "xmlns", ""); // XML_BC = XML_DOM.createNode(1,"bc", "xmlns"); // XML_BC = XML_DOM.createNode(1,"bc", "ns"); // XML_BC = XML_DOM.createNode(1,"bc", "null"); // XML_BC = XML_DOM.createNode(1,"bc", "http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01"); // XML_BC = XML_DOM.createElement("bc"); XML_QF.appendChild(XML_BC); ДобавитьТекст(XML_DOM, XML_BC, СокрЛП(ТЗ.ПолучитьЗначение(Сч, "ШК"))); КонецЦикла; ДобавитьАттрибут, ДобавитьТекст, это функции в ГМ, в данном случае они не интересны... Все, что закомментировано - это я "экспериментировал", "плясал с бубном", безрезультатно... |
|||
1
SleepyHead
гуру
08.10.19
✎
05:08
|
Да не мучайся и пиши сразу файл как обычный текст.
|
|||
2
BalBess
08.10.19
✎
05:49
|
(1) а можно чуть подробнее, в смысле чем это делать
|
|||
3
Ясный перец
08.10.19
✎
05:52
|
Создать объект текст и писать в него то, что нужно.
|
|||
4
trdm
08.10.19
✎
07:09
|
(2) что-то вроде:
//============================================================================== // ВыгрузитьСписокДОкументов( псСписок ) © trdm 2018-05-16 18:40 Функция ВыгрузитьСписокДОкументов( псСписок ) ЗначВозврата = 1; Если псСписок.РазмерСписка() = 0 Тогда Сообщить("Нечего выгружать!"); Возврат 0; КонецЕсли; СформироватьИмяФайлаВыгрузки(2); вИмяФайлаВыгрузки = СокрЛП(ВыбИмяФайлаВыгрузки); вСкриптОбж = СоздатьОбъект("Scripting.FileSystemObject"); Попытка вТекстСтрим=вСкриптОбж.OpenTextFile(вИмяФайлаВыгрузки, 8, 1, 0); Исключение Возврат 0; КонецПопытки; вТекстСтрим.WriteLine("<?xml version=""1.0"" encoding=""windows-1251""?>"); вТекстСтрим.WriteLine("<packet>"); вТекстСтрим.WriteLine("<documents>"); вСохрСтрока = ""; СЦ = 0; Для СЦ = 1 По псСписок.РазмерСписка() Цикл вДокум = псСписок.ПолучитьЗначение(СЦ); глБегущийКурсор(вСохрСтрока,"Обр.:"+вДокум); ВыгрузитьДокументВ_XMLФайл2(вТекстСтрим, вДокум); КонецЦикла; вТекстСтрим.WriteLine("</documents>"); вТекстСтрим.WriteLine("</packet>"); вТекстСтрим.Close(); Сообщить("Выгрузили в: "+вИмяФайлаВыгрузки); Возврат ЗначВозврата; КонецФункции // ВыгрузитьСписокДОкументов() |
|||
5
trdm
08.10.19
✎
07:14
|
+(4) Несколько хелперов:
////****************************************************************************** ////**********ФУНКЦИИ ДЛЯ РАБОТЫ С XML-ФАЙЛАМИ (НАЧАЛО)*************************** // //****************************************************************************** // глИнициализироватьХМЛ(Объект, Узел1гоУровня, НазваниеУзла1гоУровня = "Данные", СхемаЗаполненияУзла1гоУровня = 0) // <<© ТрДм 2005>> // Инициализирует "Объект" созданным MSXML2.DOMDocument. // Создает и ассигнует переменной "Узел1гоУровня" узел с названием из "НазваниеУзла1гоУровня" // Если переменная "НазваниеУзла1гоУровня" содержит данные и "СхемаЗаполненияУзла1гоУровня">0 // Тогда в узле "Узел1гоУровня" создается предопределенная схема по номеру из "СхемаЗаполненияУзла1гоУровня" // СписокАтрибутовДанных - объект "списокзначений", содержащий // В случае успеха возвращает "1", в случае не успеха "0" или отрицательное число Функция глИнициализироватьХМЛ(ХМЛ, Узел1гоУровня = "", НазваниеУзла1гоУровня = "", псПоАнглийски = 0) Экспорт//, СхемаЗаполненияУзла1гоУровня = 0, СписокАтрибутовДанных = "") Попытка ХМЛ = СоздатьОбъект("MSXML2.DOMDocument"); Исключение Сообщить("Ошибка при создании объекта: ''MSXML2.DOMDocument'' ","!!!"); Возврат 0; КонецПопытки; Заголовок = ХМЛ.createProcessingInstruction("xml", "version=""1.0"" encoding=""windows-1251""" ); ХМЛ.appendChild(Заголовок); Если НазваниеУзла1гоУровня<>"" Тогда Узел1гоУровня = ХМЛ.createElement(НазваниеУзла1гоУровня); ХМЛ.appendChild(Узел1гоУровня); вВерсия = СокрЛП(Константа.НомерРелиза)+"-"+СокрЛП(Константа.НомерРелизаДоп); Если псПоАнглийски = 0 Тогда Узел1гоУровня.setAttribute("ИБ",КаталогИБ()); Узел1гоУровня.setAttribute("Оператор",ИмяПользователя()); Узел1гоУровня.setAttribute("Дата",Строка(РабочаяДата())); Узел1гоУровня.setAttribute("Время",Строка(ТекущееВремя())); Узел1гоУровня.setAttribute("КодИБ",Строка(Константа.КодИБ)); Узел1гоУровня.setAttribute("Версия",вВерсия); ИначеЕсли псПоАнглийски = 1 Тогда Узел1гоУровня.setAttribute("IB",КаталогИБ()); Узел1гоУровня.setAttribute("Operator",ИмяПользователя()); Узел1гоУровня.setAttribute("Data",Строка(РабочаяДата())); Узел1гоУровня.setAttribute("Time",Строка(ТекущееВремя())); Узел1гоУровня.setAttribute("version",вВерсия); КонецЕсли; КонецЕсли; Возврат 1; КонецФункции // глИнициализироватьХМЛ() // Создает узел с именнем "элемент", подчиненный узлу "папа" // Если передан текст в "ТекстЭлемента", тогда устанавливается атрибут "дитя.text" = ТекстЭлемента // Объект - "MSXML2.DOMDocument" // папа - один из существующих уже узлов // Возвращает созданный элемент. // <<© elisabet 2005>> [email protected] Функция глСоздатьПодчиненныйХМЛ(ОбъектХМЛ,УзелПапа,НаимЭлемента, ТекстЭлемента = 0, КакАтрибут = 0) Экспорт Если КакАтрибут = 0 Тогда дитя = ОбъектХМЛ.createElement(НаимЭлемента); Попытка УзелПапа.appendChild(дитя); Исключение глСообщитьОбОшибке(ОписаниеОшибки() + " дитя: "+дитя+" [20160720-1255]"); КонецПопытки; Если ПустоеЗначение(ТекстЭлемента) = 0 Тогда Попытка дитя.text = Строка(ТекстЭлемента); Исключение глСообщитьОбОшибке(ОписаниеОшибки()+"[200612011243]"); КонецПопытки; КонецЕсли; Иначе //УзелПапа = msxml2_domdocumentixmldomelement дитя = УзелПапа.setAttribute(НаимЭлемента,Строка(ТекстЭлемента)); КонецЕсли; Возврат дитя; КонецФункции Функция глСоздатьПодчиненныйХМЛ_CDATA(ОбъектХМЛ,УзелПапа,НаимЭлемента, ТекстЭлемента = "") Экспорт дитя = ОбъектХМЛ.createCDATASection(НаимЭлемента); УзелПапа.appendChild(дитя); Если ПустоеЗначение(ТекстЭлемента) = 0 Тогда Попытка дитя.text = Строка(ТекстЭлемента); Исключение глСообщитьОбОшибке(ОписаниеОшибки()+"[200612011243]"); КонецПопытки; КонецЕсли; Возврат дитя; КонецФункции // Создает узел с именнем "элемент", подчиненный узлу "папа" // Если передан текст в "ТекстЭлемента", тогда устанавливается атрибут "дитя.text" = ТекстЭлемента // Объект - "MSXML2.DOMDocument" // папа - один из существующих уже узлов // Возвращает созданный элемент. // <<© elisabet 2005>> [email protected] Функция глДобавитьАтрибутыИзСпискаХМЛ(ОбъектХМЛ,УзелПапа,СписокАтрибутов, КакАтрибут=0) Экспорт Если ТипЗначенияСтр(СписокАтрибутов) = "СписокЗначений" Тогда СЦ = 0; Для СЦ = 1 По СписокАтрибутов.РазмерСписка() Цикл НаимЭлемента = ""; ТекстЭлемента = СписокАтрибутов.ПолучитьЗначение(СЦ, НаимЭлемента); Если НаимЭлемента<>"" Тогда глСоздатьПодчиненныйХМЛ(ОбъектХМЛ,УзелПапа,НаимЭлемента, ТекстЭлемента,КакАтрибут); КонецЕсли; КонецЦикла; Иначе Возврат 0; КонецЕсли; Возврат 1; КонецФункции |
|||
6
trdm
08.10.19
✎
07:20
|
использовать:
гХМЛУзел1 = ""; гХМЛ = СоздатьОбъект("MSXML2.DOMDocument"); Если глИнициализироватьХМЛ(гХМЛ, гХМЛУзел1,"zakout",1) = 0 Тогда Возврат; КонецЕсли; гХМЛ.async = 0; вСписОтправленных = СоздатьОбъект("СписокЗначений"); гПомошникОтчета93.ПриНачалеФормированияОтчетаПлюс( Контекст, "ВыгрузитьДанныеНаСайт" ); вВерсия = СокрЛП(Константа.НомерРелиза)+"-"+СокрЛП(Константа.НомерРелизаДоп); гХМЛУзел1.setAttribute("version",вВерсия); гХМЛУзел1.setAttribute("fl_proc",гВнешнийФайлОбработкиПолнИмя); гХМЛУзел1.setAttribute("iteract",псИнтерактивно); вВыгружено = 0; вУзел2уровня = глСоздатьПодчиненныйХМЛ(гХМЛ, гХМЛУзел1,"ordersstate"); вСписАтрибутов = СоздатьОбъект("СписокЗначений"); вСписАтрибутов.ДобавитьЗначение("Статусы заказов","descr"); глДобавитьАтрибутыИзСпискаХМЛ(гХМЛ, вУзел2уровня,вСписАтрибутов,1); .... гХМЛ.save(гИмяФайлаПолноеЗаказы); //сообщитьСЛогом("ВыгрузитьДанныеНаСайт - Точка 4"); |
|||
7
NorthWind
08.10.19
✎
07:20
|
(0) А вы все еще пользуете DOM для таких целей? Я поступаю проще. Создаю текстовый шаблончик вида
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <DESADV> <NUMBER>%DOCNUM</NUMBER> <DATE>%DOCDATE</DATE> <CAMPAIGNNUMBER>%CAMPAIGNNUMBER</CAMPAIGNNUMBER> <ORDERNUMBER>%ORDERNUM</ORDERNUMBER> <ORDERDATE>%ORDERDATE</ORDERDATE> ... и потом меняю все %DOCNUM, %CAMPAIGNNUMBER, %ORDERNUM и прочие на значимые атрибуты. Если в XML есть повторяющиеся позиции - ну значит шаблончиков будет два - один для тела, второй для позиции. Это дико упрощает жизнь - при обновлении очередного госдокумента вы просто заменяете шаблон и в худшем случае дописываете логику по измененным атрибутам. |
|||
8
NorthWind
08.10.19
✎
07:21
|
и никаких парсеров, никакого головняка с неймспейсами...
|
|||
9
Salimbek
08.10.19
✎
10:01
|
(0) Еще можно попробовать 1С++ и встроенное в него XmlLiteWriter отсюда: http://www.1cpp.ru/forum/YaBB.pl?num=1332077808/0#0
|
|||
10
BalBess
08.10.19
✎
10:02
|
(3) (4) (7) - эти способы работают, если размер формируемого файла 100Мб ?
|
|||
11
NorthWind
08.10.19
✎
10:09
|
(10) можно упереться в максимальную длину строки (v8: Максимальная длина строки), максимальный размер текстового файла и т.д.
В любом случае оверхед на этих операциях гораздо меньше чем на DOM, соответственно, и обходиться должно проще. |
|||
12
Garykom
гуру
08.10.19
✎
10:37
|
DOM нормально, но выкинь нафуй Msxml2.MXNamespaceManager.6.0
И что у тебя в ДобавитьУзел? |
|||
13
MWWRuza
гуру
08.10.19
✎
10:44
|
(8)Для конкретно этой задачи - может и проще. Все равно в файл DOM сохранять приходится, так, как он большой, и заслать его на прямую, скриптом не получается - 1С падает, если объем DOM превышает 570 кб. Поэтому, в данной задаче сохраняю в файл и с помощью curl отправляю. В других случаях, отправляю DOM напрямую, без сохранения в файл, обычно эти запросики маленькие...
(12)И что у тебя в ДобавитьУзел? Да в принципе, то-же самое, что и тут, и с другими XML работает, вот все функции ГМ: Функция ДобавитьУзел(XML_DOM, XML_HELPER, XML_NODE, Имя, Префикс) Экспорт XML_CHILD = XML_DOM.createNode(1,Префикс+":"+Имя,XML_HELPER.getURI(Префикс)); XML_NODE.appendChild(XML_CHILD); Возврат XML_CHILD; КонецФункции Процедура ДобавитьАттрибут(XML_DOM, XML_NODE, Имя, Значение) Экспорт XML_ATTR = XML_DOM.createAttribute(Имя); XML_ATTR.nodeValue = Значение; XML_NODE.setAttributeNode(XML_ATTR); КонецПроцедуры Процедура ДобавитьТекст(XML_DOM, XML_NODE, Значение) Экспорт Попытка XML_TEXT = XML_DOM.createTextNode(Значение); XML_NODE.appendChild(XML_TEXT); Исключение Сообщить("Ошибка: " + Значение); КонецПопытки; КонецПроцедуры |
|||
14
MWWRuza
гуру
08.10.19
✎
10:47
|
Здесь я специально не стал пользоваться функцией ГМ, так, как в этом месте мне нужно добавить узел без префикса. А он все равно добавляет NS по умолчанию: "xmlns=", явно, после имени элемента.
|
|||
15
MWWRuza
гуру
08.10.19
✎
10:47
|
"xmlns="""
|
|||
16
NikVars
08.10.19
✎
10:55
|
(0) Формируй, как получается. Далее сохраняй файл. Потом открывай его как текст и обрабатывай как нужно. Там все просто. Находи строки со своим бс и заменяй Васю на Петю. Сохраняй файл. Правда кодировку ЮТФ-8 в 7-ке ты не получишь стандартно. Но есть образцы преобразования в 7.7 в регламентированных отчетах.
Речь-то про 7.7 или 8-ку? |
|||
17
DES
08.10.19
✎
10:58
|
(0) -----Нет, я конечно понимаю, что можно пробежаться программно по тексту XML и тупо заменить " xmlns=""" на "", не проблема... Но, это как-то не красиво.
Зато быстро, дешево и надежно |
|||
18
Garykom
гуру
08.10.19
✎
11:02
|
(17) Сначала создаем себе трудности а потом героически их преодолеваем...
|
|||
19
Garykom
гуру
08.10.19
✎
11:03
|
(18)+ Это намек что совершенно случайно "xmlns=" может оказаться внутри текста или значения атрибута и заменять не нуна
|
|||
20
MWWRuza
гуру
08.10.19
✎
11:04
|
(16)Про семерку.
В принципе, уже сделал, еще ночью, и это работает: Тхт = СоздатьОбъект("Текст"); Тхт2 = СоздатьОбъект("Текст"); Тхт.Открыть("c:\Temp\1234.xml"); Для Сч = 1 По Тхт.КоличествоСтрок() Цикл Стр = Тхт.ПолучитьСтроку(Сч); НевСтр = СтрЗаменить(Стр," xmlns=""""",""); Тхт2.ДобавитьСтроку(НевСтр); КонецЦикла; Тхт2.Записать("c:\Temp\1234.xml"); И даже файл уходит по назначению без ошибок... Странно, с кодировкой проблем не возникло, тоже боялся этого. Но, как-то это "некузяво"... Наверняка, этот костыль можно как-то обойти... С практической точки зрения - наплевать, все и так работает. А вот разобраться, можно ли штатно, без костылей такое сделать - хотелось-бы... (18)Ну, да... Поэтому хочется понять, как их обойти. (19) В данной задаче - такого не будет, точно. Но, все-же... |
|||
21
MWWRuza
гуру
08.10.19
✎
11:09
|
+(20)Странно, с кодировкой проблем не возникло
Не возникло, как я понимаю, потому, что в данных нет кирилицы. Только латинские буквы и цифры. |
|||
22
Salimbek
08.10.19
✎
11:09
|
Вот, нашел у себя, баловался когда-то:
хмл = СоздатьОбъект("1cpp.XmlLiteWriter"); бд = СоздатьОбъект("BinaryData"); бд.ПодключитьсяКФайлу("C:\Bases\Site\import.xml"); бд.Размер(0); хмл.SetOutput(бд); хмл.Indent=1; хмл.WriteStartDocument(); хмл.WriteStartElement("","КоммерческаяИнформация"); хмл.WriteAttributeString("","ВерсияСхемы","","2.08"); Ч=0; М=0; С=0; ТекущееВремя(Ч,М,С); тВремя=Формат(Ч,"Ч(0)2.0")+":"+Формат(М,"Ч(0)2.0")+":"+Формат(С,"Ч(0)2.0"); хмл.WriteAttributeString("","ДатаФормирования","",Формат(ТекущаяДата(),"ДГГГГ-ММ-ДД")+"T"+тВремя); хмл.WriteStartElement("","Классификатор"); хмл.WriteElementString("","Ид","",1); хмл.WriteElementString("","Наименование","","Основной классификатор"); хмл.WriteStartElement("","ТипыЦен"); хмл.WriteStartElement("","ТипЦены"); хмл.WriteElementString("","Ид","",зТипЦенРоз.Код); хмл.WriteElementString("","Наименование","","Розничная"); хмл.WriteElementString("","Валюта","","руб."); хмл.WriteEndElement();//ТипЦены хмл.WriteStartElement("","ТипЦены"); хмл.WriteElementString("","Ид","",зТипЦенОпт.Код); хмл.WriteElementString("","Наименование","","Оптовая"); хмл.WriteElementString("","Валюта","","руб."); хмл.WriteEndElement();//ТипЦены хмл.WriteEndElement();//ТипыЦен хмл.WriteEndElement();//Классификатор хмл.WriteStartElement("","Каталог"); хмл.WriteAttributeString("","СодержитТолькоИзменения","","false"); хмл.WriteElementString("","Ид","",1); хмл.WriteElementString("","Наименование","","Основной каталог"); хмл.WriteElementString("","ИдКлассификатора","",1); хмл.WriteStartElement("","Товары"); ТекстЗапроса = " |select | Nom as ИД | , Nom [Товар :Справочник.Номенклатура] |from ( |select distinct Номенклатура Nom |from РегистрИтоги_ОстаткиТМЦ | where period=(select max(period) from РегистрИтоги_ОстаткиТМЦ) | and Склад=:Склад) as V |"; база.Открыть(":memory:"); рс = база.НовыйЗапрос(); рс.Подставлять("Склад",зСклад.ТекущийЭлемент()); тз = рс.ВыполнитьЗапрос(ТекстЗапроса); //тз = СоздатьОбъект("ТаблицаЗначений"); тз.ВыбратьСтроки(); Пока тз.ПолучитьСтроку() = 1 Цикл хмл.WriteStartElement("","Товар"); хмл.WriteElementString("","Ид","",тз.ИД); хмл.WriteStartElement("","Артикул"); хмл.WriteEndElement();//Артикул хмл.WriteElementString("","Наименование","",тз.Товар.Наименование); хмл.WriteElementString("","Описание","",тз.Товар.Наименование); хмл.WriteStartElement("","БазоваяЕдиница"); хмл.WriteAttributeString("","Код","",тз.Товар.БазоваяЕдиница.ОКЕИ.Код); хмл.WriteAttributeString("","НаименованиеКраткое","",тз.Товар.БазоваяЕдиница.ОКЕИ.Наименование); хмл.WriteAttributeString("","НаименованиеПолное","",СокрЛП(тз.Товар.БазоваяЕдиница.ОКЕИ.ПолнНаименование)); хмл.WriteEndElement();//БазоваяЕдиница хмл.WriteEndElement();//Товар КонецЦикла; хмл.WriteEndElement();//Товары хмл.WriteEndElement();//Каталог хмл.WriteEndElement();//КоммерческаяИнформация хмл.WriteEndDocument(); хмл.Release(); бд.Закрыть(); |
|||
23
Salimbek
08.10.19
✎
11:11
|
И вот еще...
ЗагрузитьВнешнююКомпоненту("..\Src\OpenXML.dll") xml = СоздатьОбъект("AddIn.OpenXML"); имяф=КаталогИБ()+"tovar1.xml"; Сообщить("Запись XML-файла: "+имяф); xml.СоздатьФайл(имяф); xml.ЗаписатьТег("<Товары>"); о=СоздатьОбъект("Справочник.Товары"); о.ВыбратьЭлементы(); Пока о.ПолучитьЭлемент()=1 Цикл Если о.ЭтоГруппа()=1 Тогда Продолжить; КонецЕсли; Если о.ПометкаУдаления()=1 Тогда Продолжить; КонецЕсли; xml.ЗаписатьТег("<Элемент>"); xml.ЗаписатьЗначение("<Код>", ""+о.Код); xml.ЗаписатьЗначение("<Наименование>", ""+СокрЛП(о.Наименование)); xml.ЗаписатьЗначение("<Единица>", ""+СокрЛП(о.Единица)); xml.ЗаписатьЗначение("<Цена>",""+о.Цена); xml.ЗаписатьТег("</Элемент>"); КонецЦикла; xml.ЗаписатьТег("</Товары>"); xml.ЗакрытьФайл(); |
|||
24
NikVars
08.10.19
✎
11:12
|
(21) Не, этого мало. Ты сконверитурую в текстовом редакторе в из вин в ютф. Сразу увидишь размеры разные...
И еще в ютф, там конец строки иной, чем в вин-кодировке. Говорю же, есть примеры в реготчетах в 7.7. Ищи по UTF по всем отчетам. |
|||
25
MWWRuza
гуру
08.10.19
✎
11:17
|
(22) Спасибо за пример... Надо будет как-нибудь попробовать. Но, пока обходился MS XML DOM 6.0 Везде, по всей конфигурации работы с ЕГАИС, а их там огромная куча, там все на XML построено. Первая задача, где такое встретилось.
(24) Согласен... Но, работает! И файл UTM глотает, без ошибок, и ответ выдает, со списком марок, которые в нем отсутствуют. Что, собственно и требовалось. |
|||
26
NikVars
08.10.19
✎
11:20
|
(25) Все равно разберись. А то действительно начнут требовать именно ЮТФ, и именно в неудобный для тебя момент времени, и будут выдавать сообщение об ошибке по которому фик чего сообразишь...
:) |
|||
27
NorthWind
08.10.19
✎
11:25
|
(25) я все-таки рекомендую (7) прочитать. От DOM при формировании (не при чтении) документов я отказался еще в 16 году и еще ни разу не было повода пожалеть об этом.
|
|||
28
trad
08.10.19
✎
11:28
|
(0)
//******************************************* Функция ДобавитьЭлемент(ДокXML, Родитель, ИмяЭлемента, Значение = "") Узел = ДокXML.createElement(ИмяЭлемента); Если Значение <> "" Тогда Узел.text = Строка(Значение); КонецЕсли; Возврат Родитель.appendChild(Узел); КонецФункции //******************************************* Процедура Сформировать() ДокXML = СоздатьОбъект("Msxml2.DOMDocument"); ДокXML.appendChild(ДокXML.createProcessingInstruction("xml", "version = ""1.0"" encoding = ""UTF-8""")); Documents = ДобавитьЭлемент(ДокXML, ДокXML, "ns:Documents"); Documents.setAttribute("Version", "1.0"); Documents.setAttribute("xmlns:xs", "http://www.w3.org/2001/XMLSchema"); Documents.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); Documents.setAttribute("xmlns:ns", "http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01"); Documents.setAttribute("xmlns", "http://fsrar.ru/WEGAIS/QueryFilter"); ДобавитьЭлемент(ДокXML, ДобавитьЭлемент(ДокXML, Documents, "ns:Owner"), "ns:FSRAR_ID", "02000012****"); Document = ДобавитьЭлемент(ДокXML, Documents, "ns:Document"); QueryFilter = ДобавитьЭлемент(ДокXML, Document, "ns:QueryFilter"); ДобавитьЭлемент(ДокXML, QueryFilter, "bc", "101200026723**********************"); ДобавитьЭлемент(ДокXML, QueryFilter, "bc", "101200026723**********************"); ДокXML.save("c:\test.xml"); КонецПроцедуры |
|||
29
trad
08.10.19
✎
11:28
|
(28)
<?xml version="1.0" encoding="utf-8"?> <ns:Documents Version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns="http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01" xmlns="http://fsrar.ru/WEGAIS/QueryFilter"> <ns:Owner> <ns:FSRAR_ID>02000012****</ns:FSRAR_ID> </ns:Owner> <ns:Document> <ns:QueryFilter> <bc>101200026723**********************</bc> <bc>101200026723**********************</bc> </ns:QueryFilter> </ns:Document> </ns:Documents> |
|||
30
MWWRuza
гуру
08.10.19
✎
11:37
|
(26)Сейчас посмотрел, что-то найти пока не получилось... Например файл "RPUNLD40.ERT", это как раз выгрузка отчетов, по "UTF" ничего не находит. Вообще, там XML при помощи v7plus формируются, может по этому и не нужно кодировку указывать.
(28), (29), спасибо... Сейчас попробую. Только есть небольшое сомнение - лишние атрибуты в заголовке, не будут мешать? В примере файла для УТМ, из описания, строка заголовка такая: "<ns:Documents xmlns="http://fsrar.ru/WEGAIS/QueryFilter" xmlns:ns="http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01" Version="1.0">" Хотя, лишние атрибуты по идее не должны мешать... |
|||
31
NikVars
08.10.19
✎
11:43
|
(30) Отчетность 3 кв 2019. Файл RSV14.ERT, например.
Если флОшибкаВВыгрузке = 0 Тогда ИмяФайлаВыгрузкиФЛ = СокрЛП(КаталогВыгрузкиФЛ) + "\" + ИмяФайлаВыгрузки + ".xml"; РезФайл = СоздатьОбъект("AddIn.V7TextFile"); РезФайл.ОткрытьФайл(ИмяФайлаВыгрузкиФЛ, 1); РезФайл.ЗаписатьСтроку("<?xml version=""1.0"" encoding=""UTF-8""?>"); ЗаписатьУзелВФайл(РезФайл, xmlФайлВыгрузкиФЛ.ЭлементДокумента); РезФайл.ЗакрытьФайл(); ТекстФайл = СоздатьОбъект("Текст"); ТекстФайл.Открыть(ИмяФайлаВыгрузкиФЛ); ИзменяемаяСтрока = ТекстФайл.ПолучитьСтроку(2); ИзменяемаяСтрока = СтрЗаменить(ИзменяемаяСтрока, "xsi", "xmlns:xsi"); ИзменяемаяСтрока = СтрЗаменить(ИзменяемаяСтрока, "noNamespaceSchemaLocation", "xsi:noNamespaceSchemaLocation"); ТекстФайл.ЗаменитьСтроку(2, ИзменяемаяСтрока); ТекстФайл.Записать(ИмяФайлаВыгрузкиФЛ); //Сохраняем файл в кодировке UTF-8 Если КолДопЛистов <= 2500 Тогда АдоДБСтрим = СоздатьОбъект("Adodb.Stream"); АдоДБСтрим.Charset = "windows-1251"; АдоДБСтрим.Type = 2; АдоДБСтрим.Mode= 3; АдоДБСтрим.Open(); АдоДБСтрим.LoadFromFile(ИмяФайлаВыгрузкиФЛ); ТекстАдоДБСтрим = АдоДБСтрим.ReadText(); АдоДБСтрим.Close(); АдоДБСтрим.Charset = "utf-8"; АдоДБСтрим.Open(); АдоДБСтрим.WriteText(ТекстАдоДБСтрим); АдоДБСтрим.SaveToFile(ИмяФайлаВыгрузкиФЛ, 2); АдоДБСтрим.Close(); Сообщить("Сформирован файл: " + ИмяФайлаВыгрузкиФЛ); Иначе Сообщить("Сформирован файл: " + ИмяФайлаВыгрузкиФЛ); Сообщить("Сформированый файл содержит данные более 2500 физических лиц и его не удалось сохранить в кодировке UTF-8.", "!"); Сообщить("Рекомендуется сформированный файл открыть в текстовом редакторе и сохранить в кодировке UTF-8.", "!"); КонецЕсли; Иначе Сообщить(НазваниеРегФормы + ": " + НазваниеРазделаРегФормы + ": |Не удалось выгрузить данные о физических лицах.", "!!"); КонецЕсли; |
|||
32
NikVars
08.10.19
✎
11:49
|
(30) Сказал же, - по всем отчетам. Ты сузил область поиска до ненужного и бесполезного...
|
|||
33
trdm
08.10.19
✎
11:56
|
(10) По производительности лучше всего (4).
|
|||
34
MWWRuza
гуру
08.10.19
✎
19:05
|
Отчитываюсь...
trad, спасибо! Сделал как в (28), только убрал два лишних атрибута NS, вот эти две строки: Documents.setAttribute("xmlns:xs", "http://www.w3.org/2001/XMLSchema"); Documents.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance"); Кроме того, не работает с объектом "MSXML2.DOMDocument.6.0" - с ним записывается все равно в строки "xmlns=""", хоть что делай. Создаешь "MSXML2.DOMDocument", без "6.0", все начинает работать нормально. А вообще, это какой-то нонсенс... Все в этом запросе к УТМ через Ж... сделано. С него прилетает в ответ XMLка, которая тоже MS XML DOMом не парситя нормально... Вот фрагмент: <?xml version="1.0" encoding="UTF-8" standalone="no"?> <ns:Documents xmlns="http://fsrar.ru/WEGAIS/QueryFilter" xmlns:ns="http://fsrar.ru/WEGAIS/WB_DOC_SINGLE_01" Version="1.0"> <ns:Owner> <ns:FSRAR_ID>0200001****</ns:FSRAR_ID> </ns:Owner> <ns:Document> <ns:ReplyFilter> <result>Штрихкод не найден</result> <bc>10120002672311****************</bc> <bc>10120002672317****************</bc> Казалось бы, все нормально... Но, похоже из за того, что узлы с префиксами а сами элементы последнего уровня без префиксов, он их не видид как отдельные элементы! Все что подчинено узлу ReplyFilter, видится как один элемент, такая длинная строка... Хорошо, хоть пробелами элементы разделены... Метод XML_DOM.selectNodes("/ns:Documents/ns:Document/ns:ReplyFilter"), возвращает выборку, в которой один элемент, эта самая строка! Вот так я ее получаю: ContentNodes.item(0).text, в ней содержимое всех узлов "bc", через пробелы... Пришлось парсить строку, вот так: Стр = СтрЗаменить(Стр,"Штрихкод не найден ",""); ПозПроб = Найти(Стр, " "); Пока ПозПроб > 0 Цикл СЗ.ДобавитьЗначение(Лев(Стр,ПозПроб - 1)); Стр = Сред(Стр, ПозПроб + 1); ПозПроб = Найти(Стр, " "); КонецЦикла; Возврат СЗ; Дурдом... В конечном счете, все заработало, цель(получить список марок, отсутствующих в УТМ) достигнута... Но, как-то криво все, морального удовлетворения не принесло, не люблю я такой код... PS Видимо, это по тому, что этот запрос в ЕГАИС обособленно стоит... Может даже другими разработчиками делался. Все дело в том, что это единственный запрос, который не транслируется на сервер ЕГАИС, а выполняется к локальной базе УТМ. Все, что транслируется на сервер, работает от 2 до 5+ минут, этот же выполняется мгновенно, но вот с такими косячными XML... |
|||
35
Злопчинский
08.10.19
✎
20:43
|
(7) а ведь действительно, при формировании иксемеля я не додумался применять такую, а ведь в других местах использую аналогичное.
то есть ты читаешь шаблончик, заменяешь и пихаешь получившееся в конечный вывод? ведь в конечном выводе блоки шаблончиков могут повторяться несколько раз (строки например), типа так? |
|||
36
Злопчинский
08.10.19
✎
20:46
|
Полезняшки, может ком упригодятся из мохнатых мамонтов со склерозом.. ;-)
|
|||
37
Злопчинский
08.10.19
✎
20:53
|
//********************************************************************************************************************************
// http://www.skalnyy.com/1s-perekodirovka-fajla/ // ВОЗМОЖНЫЕ ВАРИАНТЫ КОДИРОВОК "UTF-8" "KOI8-R" "Windows-1251" "ISO-8859-5" Процедура глИзменитьКодовуюСтраницуФайла(имяФайла, исходнКодировка, нужнаяКодировка) Экспорт Если ФС.СуществуетФайл(имяФайла) = 0 Тогда Сообщить("Файл " + имяФайла + " - не найден! Изменение кодировки отменено.", "!"); Возврат; КонецЕсли; ScrptCtrl = СоздатьОбъект("MSScriptControl.ScriptControl"); ScrptCtrl.Language = "VBScript"; ScrptCtrl.AddCode(" |Function StrConv(Text,SourceCharset,DestCharset) | Set Stream=CreateObject(""ADODB.Stream"") | Stream.Type=2 | Stream.Mode=3 | Stream.Open | Stream.Charset=DestCharset | Stream.WriteText Text | Stream.Position=0 | Stream.Charset=SourceCharset | StrConv=Stream.ReadText |End Function | |sub ConvertCodepage( fileName, SourceCharset, DestCharset ) | set fs = CreateObject(""Scripting.FilesystemObject"") | originalText = fs.openTextFile(fileName,1).readAll() | convertedText = strConv(originalText, SourceCharset, DestCharset ) | fs.openTextFile(fileName,2,true).write(convertedText) |end sub | |"); Module = ScrptCtrl.Modules("Global"); CodeObject = Module.CodeObject; CodeObject.ConvertCodepage(имяФайла, исходнКодировка, нужнаяКодировка); КонецПроцедуры //ИзменитьКодовуюСтраницуФайла() |
|||
38
Злопчинский
08.10.19
✎
20:55
|
//********************************************************************************************************************************
// Функция глПреобразоватьСтрокуВUTF8(Стр) Экспорт Длина=СтрДлина(Стр); //ОТЛАДКА //Возврат Стр; Итог=""; Для Н=1 По Длина Цикл Знак = Сред(Стр,Н,1); Код = КодСимв(Знак); Если Код<128 Тогда Итог = Итог + Знак; Иначе Если (Код>=КодСимв("А"))И(Код<=КодСимв("п")) Тогда Итог=Итог+Симв(208)+Симв(144+Код-КодСимв("А")); ИначеЕсли (Код>=КодСимв("р"))И(Код<=КодСимв("я")) Тогда Итог=Итог+Симв(209)+Симв(128+Код-КодСимв("р")); ИначеЕсли (Знак="ё") Тогда Итог=Итог+Симв(209)+Симв(145); ИначеЕсли (Знак="Ё") Тогда Итог=Итог+Симв(208)+Симв(129); КонецЕсли; КонецЕсли; КонецЦикла; Возврат Итог; КонецФункции //глПреобразоватьСтрокуВУТФ8() |
|||
39
NorthWind
08.10.19
✎
20:58
|
(35) Если блоки повторяются несколько раз, то просто делается два шаблона - один на тело, второй на повторяющуюся секцию (позицию). "Позиционный" заполняется и добавляется в строку столько раз, сколько позиций, а потом в шаблоне "тела" им заменяется единственная подстановка. Такая же система с дополнительным шаблоном для секций, которые в зависимости от каких-то условий могут быть, а могут и не быть.
|
|||
40
NorthWind
08.10.19
✎
21:02
|
это реально оказалась очень полезная вещь для всяких документооборотов. Например, сейчас идет изменение в сетях форматов электронного УПД - у кого-то старый, у кого-то уже новый. Не будь шаблонов - пришлось бы два отдельных модуля делать или напихивать условия в код. А так просто в базу подвесил два набора шаблончиков - и вуаля, у одного в соответствии старый, у другого новый, если все требуемые атрибуты обрабатываются - вообще все правится не заходя в конфигуратор.
|
|||
41
NorthWind
08.10.19
✎
21:15
|
Разумеется, эта фигня не универсальная. Например, если в зависимости от входных данных результирующий XML может терять или получать 50-80% всех атрибутов, то она вряд ли подойдет, слишком много разных шаблонов придется делать. И нужно иметь в виду, что строки в XML = строкам в HTML, т.е. нужно заменять некоторые символы на литералы. В снеговике я делаю примерно так:
Функция СтрокаHTML (ВхСтрока) Результат = ВхСтрока; МассивИзменений = Новый Массив; МассивИзменений.Добавить (Новый Структура ("Что,НаЧто", "&", "&")); МассивИзменений.Добавить (Новый Структура ("Что,НаЧто", "<", "<")); МассивИзменений.Добавить (Новый Структура ("Что,НаЧто", ">", ">")); МассивИзменений.Добавить (Новый Структура ("Что,НаЧто", """", """)); МассивИзменений.Добавить (Новый Структура ("Что,НаЧто", "'", "'")); Для Каждого Элем из МассивИзменений Цикл Результат = СтрЗаменить (Результат, Элем.Что, Элем.НаЧто); КонецЦикла; Возврат Результат; КонецФункции |
|||
42
Злопчинский
08.10.19
✎
21:35
|
(41) Плохо еще когда есть например в иксемеле заявка (тот же еди), а потом в секции каждой строки заявки надо впихнуть тег с подтверждением. тут я уже через обекты иксемеля работаю.
|
|||
43
NorthWind
08.10.19
✎
21:46
|
(42) там вроде отдельный документ ORDRSP... Я его формирую по шаблону вроде успешно, не жалуются. Оператор при обработке заявки может указать, что не будет доставлено, хотя у нас это редкий случай - мы работаем от заказа и обычно делаем все что хотят купить.
|
|||
44
Злопчинский
09.10.19
✎
02:29
|
(43) угу. сейчас точно не помню но то ли там надо было чтобы строки в подтверждении шли строго как в заявке или еще что-то. в итоге брал заявку исходную в иксемеле и вставлял строки подтверждения, т.е там формат подтвержденяи был типа
"исходная строка заявки" "тэги подтверждения". . и пофиг, что в исходной заявке и в подтверждении есть отдельный тег/атрибут "номер строки". этого недостаточно. надо чтобы в файле строки шли строго физически по порядку" |
|||
45
NorthWind
09.10.19
✎
08:30
|
(44) там еще бывает такая фишка - выдают подобные рекомендации не всегда компетентно. Пару раз подобное было, а потом пробовали делать как обычно - и все равно документы нормально принимались.
|
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |