PHP и каноникализация C14N

Цель канонизации — обеспечить, чтобы для одних и тех же данных на уровне XML не менялся хэш, необходимый для проверки подписи.  Т.е. удаляются лишние пробелы, символы и т.д. У себя реализовал примерно так:

function CanonicalXML($xml_text){
   $xml = new DOMDocument( "1.0", "utf-8" );
   $xml->loadXML($xml_text);
   $xml = $xml->C14N();
   return $xml;
}

echo CanonicalXML('<Envelope       xmlns:xsd="http://www.w3.org/2001/XMLSchema" ><Body>Привет всем!</Body  ></Envelope >');

Чтение данных из файла docx средствами 1С

Задача: спарсить данные из таблицы, которая находится в файле формата docx средствами 1С

Решение: по сути своей файл формата docx является zip архивом, в котором находятся файлы формата xml и внешние ресурсы, типа картинок, стилей и т.п. Текстовое же содержимое находится непосредственно в файле document.xml. Его нужно лишь прочитать, найти в нём таблицу и распарсить данные.

Для начала загрузим файл на сервер, переименуем его в zip, и откроем его при помощи метода 1С «ЧтениеZipФайла», а найденный в архиве файл document.xml извлекем для дальнейшей обработки:

&НаКлиенте
Процедура ВыбратьФайлыИСделатьХорошо(Команда)
	Режим = РежимДиалогаВыбораФайла.Открытие;
    ДиалогОткрытияФайла = Новый ДиалогВыбораФайла(Режим);
    ДиалогОткрытияФайла.ПолноеИмяФайла = "";
    Фильтр = НСтр("ru = 'Текст'; en = 'Text'")+ "(*.docx)|*.docx";
    ДиалогОткрытияФайла.Фильтр = Фильтр;
    ДиалогОткрытияФайла.МножественныйВыбор = ложь;
    ДиалогОткрытияФайла.Заголовок = "Выберите файлы";
    Если ДиалогОткрытияФайла.Выбрать() Тогда
        МассивФайлов = ДиалогОткрытияФайла.ВыбранныеФайлы;
		ФайлСМС="";
		Для Каждого ИмяФайла Из МассивФайлов Цикл
			ФайлСМС=ИмяФайла;
		конеццикла;
		если ФайлСМС<>"" тогда 			
					АдресХранилищаФайла = "";			
					Состояние("Перемещаю файл на сервер");
		            ПоместитьФайл(АдресХранилищаФайла, ФайлСМС, , Ложь, ЭтаФорма.УникальныйИдентификатор);   					
					Состояние("Обрабатывается файл "+ФайлСМС);							
					таблицы=ПреобразоватьФайлDocXВМассивТаблиц(АдресХранилищаФайла);					
		иначе
			сообщить("Файл не выбран");
		конецесли;	
	конецесли;	        
КонецПроцедуры

&НаСервере
Функция ПреобразоватьФайлDocXВМассивТаблиц(АдресХранилищаФайла)	
	ТЗ=Новый ТаблицаЗначений();	
	ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресХранилищаФайла);
	ИмяВременногоФайлаСпр = ПолучитьИмяВременногоФайла("zip");
	ДвоичныеДанные.Записать(ИмяВременногоФайлаСпр);     

	Архив = Новый ЧтениеZipФайла(ИмяВременногоФайлаСпр);
	ИмяВременногоФайлаXML = ПолучитьИмяВременногоФайла("xml");
	Для Каждого Элемент Из Архив.Элементы Цикл	
		если  Элемент.Имя="document.xml" тогда			
			Архив.Извлечь(Элемент, КаталогВременныхФайлов(), РежимВосстановленияПутейФайловZIP.НеВосстанавливать);			
		конецесли;
	Конеццикла;	
	Архив.Закрыть();
....

Далее файл documnet.xml необходимо загрузить как XML и распарсить в структуру при помощи построителя DOM. После чего останется только найти таблицу по имени узла w:tbl и поместить содержимое в таблицу значений:

ФайлXML = Новый ЧтениеXML;
    ФайлXML.ОткрытьФайл(КаталогВременныхФайлов()+"document.xml");
		ПостроительDOMXML=Новый ПостроительDOM;
		ДокументДом=ПостроительDOMXML.Прочитать(ФайлXML);
		ПрочитаноСтрок=0;		
		для каждого document из ДокументДом.ДочерниеУзлы цикл
			для каждого body из document.ДочерниеУзлы цикл
				для каждого el из body.ДочерниеУзлы цикл
					если el.ИмяУзла="w:tbl" тогда
							для каждого tab_el из el.ДочерниеУзлы цикл							
								если tab_el.ИмяУзла="w:tr" тогда
									если ПрочитаноСтрок=0 тогда
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[1].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[2].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[3].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[4].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[5].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[6].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[7].ТекстовоеСодержимое));
										ТЗ.Колонки.Добавить(УбратьНеОбрабатываемыеСимволы(tab_el.ДочерниеУзлы[8].ТекстовоеСодержимое));
									иначе	                 
										если tab_el.ДочерниеУзлы[1].ТекстовоеСодержимое="Всего:" тогда 
											прервать;
										КонецЕсли;           
										если tab_el.ДочерниеУзлы[1].ТекстовоеСодержимое<>"1" тогда
											если tab_el.ДочерниеУзлы[6].ТекстовоеСодержимое<>"" тогда
												нс=ТЗ.Добавить();
												нс[0]=tab_el.ДочерниеУзлы[1].ТекстовоеСодержимое;
												нс[1]=tab_el.ДочерниеУзлы[2].ТекстовоеСодержимое;
												нс[2]=tab_el.ДочерниеУзлы[3].ТекстовоеСодержимое;
												нс[3]=tab_el.ДочерниеУзлы[4].ТекстовоеСодержимое;
												нс[4]=tab_el.ДочерниеУзлы[5].ТекстовоеСодержимое;
													нс[4]=СтрЗаменить(нс[4],",",".");
													нс[4]=СтрЗаменить(нс[4]," ","");
													если нс[4]="" тогда нс[4]="0";конецесли;
													нс[4]=Число(Формат(нс[4],"ЧГ=0"));												
												нс[5]=tab_el.ДочерниеУзлы[6].ТекстовоеСодержимое;
												нс[6]=tab_el.ДочерниеУзлы[7].ТекстовоеСодержимое;
												нс[7]=tab_el.ДочерниеУзлы[8].ТекстовоеСодержимое;
													нс[7]=СтрЗаменить(нс[7],",",".");
													нс[7]=СтрЗаменить(нс[7]," ","");
													если нс[7]="" тогда нс[7]="0";конецесли;
													нс[7]=Число(Формат(нс[7],"ЧГ=0"));												
												
											конецесли;
										конецесли;
									конецесли;	
									ПрочитаноСтрок=ПрочитаноСтрок+1;
								конецесли;
							конеццикла;
							если ПрочитаноСтрок>0 тогда прервать;конецесли;
						конецесли;
						если ПрочитаноСтрок>0 тогда прервать;конецесли;
					конеццикла;
					если ПрочитаноСтрок>0 тогда прервать;конецесли;
				конеццикла;
				если ПрочитаноСтрок>0 тогда прервать;конецесли;
		конеццикла;	
	ФайлXML.Закрыть();
	Возврат ТЗ;	

Еще один вариант выгрузки остатков товаров из 1С Розница 2.2 в файл XML.

Данную обработку можно использовать как основу для выгрузки списка товаров в интернет магазин. У меня и выгрузка из 1С и загрузка на сайт самописные, потому всё просто и понятно получается.  Обработку можно скачать тут





Форматирование xml файла из коммандной строки

Задача: отформатировать удобочитаемый формат не форматированный xml громадного размера

Решение:

 




Берем погоду у Яндекса в xml формате

Задача: получить погоду на сегодня и на завтра.

Решение: воспользуемся сервисом pogoda.yandex.ru
1. Найдем свой код города по справочнику https://pogoda.yandex.ru/static/cities.xml
2. По ссылке вида http://export.yandex.ru/weather-ng/forecasts/код_города.xml, мы имеем погоду в формате xml. Распарсим её например так:
<?php
 $wz = new SimpleXMLElement($xml);
 $cn=0;
 foreach ($wz->day as $value) {
  $cnt=0;
  foreach ($value->hour as $hr) {
  if (($cnt==2) or ($cnt==12) or ($cnt==18)) {
    $t=$hr->temperature;
    $weather_condition=$hr->weather_condition[«code»];
    echo «$t;$weather_condition</br>»;
   };
   $cnt++;
  };
  $cn++;
  if ($cn==2) {die();};
}
?>



1 2