Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Скриптовые языки администрирования Windows (http://forum.oszone.net/forumdisplay.php?f=102)
-   -   [решено] Изменение xml файла со сложной многоуровневой структурой (http://forum.oszone.net/showthread.php?t=331647)

Bolshoi 04-12-2017 10:22 2782184

Изменение xml файла со сложной многоуровневой структурой
 
Прошу совета по изменению сложного xml файла. В поисковиках находил только примеры для простого xml файла.
Дан такой xml файл документа системы обмена документов:
Код:

<?xml version="1.0" encoding="windows-1251"?>
<Файл xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ИдФайл="DP_REZRUISP_2TScd6c7b34-cdb1-4074-a47a-9624d53cb1bd_2TS816590f4-9d8d-4859-960b-c0a45ad53cc4_20171204_0b8a23ec-df6b-437c-b38d-9485e2538ab4" ВерсПрог="1.0" ВерсФорм="5.01">
  <СвУчДокОбор ИдОтпр="2TS816590f4-9d8d-4859-960b-c0a45ad53cc4" ИдПол="2TScd6c7b34-cdb1-4074-a47a-9624d53cb1bd">
    <СвОЭДОтпр НаимОрг="synerdocs" ИННЮЛ="7728075928" ИдЭДО="2TS" />
  </СвУчДокОбор>
  <Документ КНД="1175012" ДатаИнфИсп="04.12.2017" ВремИнфИсп="08.15.12" НаимЭконСубСост="ООО Тестовая организация Synerdocs 1501831146">
    <СвДокПРУ>
      <НаимДок ПоФактХЖ="Документ о передаче результатов работ (Документ об оказании услуг)" НаимДокОпр="Акт о передаче результатов работ (Акт об оказании услуг)" />
      <ИдентДок НомДокПРУ="жЭKuг" ДатаДокПРУ="04.12.2017" />
      <ДенИзм КодОКВ="643" НаимОКВ="Российский рубль" КурсВал="313" />
      <СодФХЖ1>
        <ЗагСодОпер>9нoЧ3oЗъюЯ}cnпъ</ЗагСодОпер>
        <Исполнитель>
          <ИдСв>
            <СвОрг>
              <СвЮЛ НаимОрг="ООО Тестовая организация Synerdocs 1501831146" ИННЮЛ="1882647854" КПП="249310132" />
            </СвОрг>
          </ИдСв>
          <Адрес>
            <АдрРФ Индекс="342456" КодРегион="18" Город="Ижевск" НаселПункт="Пенсионная 2" />
          </Адрес>
        </Исполнитель>
        <Заказчик>
          <ИдСв>
            <СвОрг>
              <СвЮЛ НаимОрг="ООО Тестовая организация Synerdocs 1485530969" ИННЮЛ="1835056809" КПП="183301001" />
            </СвОрг>
          </ИдСв>
          <Адрес>
            <АдрРФ Индекс="426039" КодРегион="18" Город="Ижевск" />
          </Адрес>
        </Заказчик>
        <Основание НаимОсн="Наименование основания 2" НомОсн="454-11" ДатаОсн="04.12.2017" ДопСвОсн="поле для доп. сведений" />
        <Основание НаимОсн="Наименование основания 2" НомОсн="4нк84" ДатаОсн="04.12.2017" ДопСвОсн="доп сведения оснвоание 2" />
        <ИдГосКон>094440</ИдГосКон>
        <ВидОперации>яR&gt;Е\lU@"\EэyЫs</ВидОперации>
        <ОписРабот НачРабот="06.12.2017" КонРабот="28.12.2017" СтБезНДСИт="2061354" СумНДСИт="371043.72" СтУчНДСИт="2432397.72">
          <Работа Номер="1" НаимРабот="Покупка каши" НаимЕдИзм="кг" ОКЕИ="166" Цена="4535" Количество="454" СтоимБезНДС="2058890" НалСт="18%" СумНДС="370600.2" СтоимУчНДС="2429490.2" КоррСчДебет="567893456" КоррСчКредит="567893456">
            <Описание>яневая кашка</Описание>
            <ИнфПолеОписРабот Идентиф="инфа о 1 полях 1" Значен="инфа о 1 значениях 1" />
            <ИнфПолеОписРабот Идентиф="инфа о 1 полях 2" Значен="инфа о 1 значениях 2" />
          </Работа>
          <Работа Номер="2" НаимРабот="Покупка молочка" НаимЕдИзм="л." ОКЕИ="625" Цена="56" Количество="44" СтоимБезНДС="2464" НалСт="18%" СумНДС="443.52" СтоимУчНДС="2907.52" КоррСчДебет="678123546" КоррСчКредит="678123546">
            <Описание>козье</Описание>
            <ИнфПолеОписРабот Идентиф="инфа о 2 полях 1" Значен="инфа о 2 значениях 1" />
            <ИнфПолеОписРабот Идентиф="инфа о 2 полях 2" Значен="инфа о 2 значениях 2" />
          </Работа>
        </ОписРабот>
        <ОписРабот НачРабот="08.12.2017" КонРабот="20.12.2017" СтБезНДСИт="1300" СумНДСИт="234" СтУчНДСИт="1534">
          <Работа Номер="1" НаимРабот="Соль" НаимЕдИзм="кг" ОКЕИ="166" Цена="12" Количество="12" СтоимБезНДС="144" НалСт="18%" СумНДС="25.92" СтоимУчНДС="169.92" КоррСчДебет="345890123" КоррСчКредит="456789123">
            <Описание>йодированная</Описание>
            <ИнфПолеОписРабот Идентиф="инфа о 3 полях 1" Значен="инфа о 3 значениях 1" />
            <ИнфПолеОписРабот Идентиф="инфа о 3 полях 2" Значен="инфа о 3 значениях 2" />
          </Работа>
          <Работа Номер="2" НаимРабот="Перец" НаимЕдИзм="г" ОКЕИ="163" Цена="34" Количество="34" СтоимБезНДС="1156" НалСт="18%" СумНДС="208.08" СтоимУчНДС="1364.08" КоррСчДебет="456098123" КоррСчКредит="908123675">
            <Описание>кайенский</Описание>
            <ИнфПолеОписРабот Идентиф="инфа о 4 полях 1" Значен="инфа о 4 значениях 1" />
            <ИнфПолеОписРабот Идентиф="инфа о 4 полях 2" Значен="инфа о 4 значениях 2" />
          </Работа>
        </ОписРабот>
        <ИнфПолФХЖ1>
          <ТекстИнф Идентиф="первое поля для доп. инффы" Значен="значение 1" />
          <ТекстИнф Идентиф="второе поля для доп. инффы" Значен="значение 2" />
        </ИнфПолФХЖ1>
      </СодФХЖ1>
    </СвДокПРУ>
    <СодФХЖ2 СодОпер="Результаты работ переданы (услуги оказаны)" ДатаПер="28.12.2017">
      <СвПерВещи ДатаПерВещ="28.12.2017" СвПерВещ="первое сведение о передаче вещи" />
      <ИнфПолФХЖ2 Идентиф="первое нижнее поле для доп. инфы" Значен="1 значение нижнее" />
      <ИнфПолФХЖ2 Идентиф="второе нижнее поле для доп. инфы" Значен="2 значение нижнее" />
    </СодФХЖ2>
    <Подписант ОблПолн="1" Статус="1" ОснПолнПодп="Должностные обязанности">
      <ЮЛ ИННЮЛ="1882647854" НаимОрг="ООО Тестовая организация Synerdocs 1501831146" Должн="test">
        <ФИО Фамилия="N" Имя="Al" />
      </ЮЛ>
    </Подписант>
  </Документ>
</Файл>

Написал такой сценарий:
Код:


#Массив символов для генерации данных тектсовых полей#
$listtext = [Char[]]'abcd efghijklm nopqrstuvwxy zABCDEFGHIJKLMNOPQRSTUVWX YZабвгдеёжзийк лмнопрстуфхцчшщъыь эюяАБВГДЕЁЖЗИ ЙКЛМНОПРСТУФХЦЧШ ЩЪЫЬЭЮЯ1234567890*?/\|<>,.()[]{};:"!@#$%^&'
$listnum = [Char[]]'1234567890'
#Блок задания значений для параметров, определяющих пути к файлам документов#
$DPRR = "C:\Users\Администратор\Downloads\ДПРР(исхакт).xml"
#Блок задания значений для параметров подстановки в xml#

$NumDoC= -join (1..5 | Foreach-Object { Get-Random $listtext -count 1 })
$Date = Get-Date -Format "dd.MM.yyyy"
$Currency = -join (1..3 | Foreach-Object { Get-Random $listnum -count 1 })
$Zagoper= -join (1..15 | Foreach-Object { Get-Random $listtext -count 1 })
$IDgos = -join (1..6 | Foreach-Object { Get-Random $listnum -count 1 })

$ВидОперации= -join (1..15 | Foreach-Object { Get-Random $listtext -count 1 })
$НомОсн= -join (1..6 | Foreach-Object { Get-Random $listtext -count 1 })
$ДопСвОсн = -join (1..15 | Foreach-Object { Get-Random $listtext -count 1 })

$Price =-join (1..3 | Foreach-Object { Get-Random $$listnum -count 1 })


#Изменение документа Исх. ДПРР#
$xml = New-Object -TypeName System.Xml.XmlDocument
$xml.load($DPRR) 
$xml.Файл.Документ.СвДокПРУ.ИдентДок.НомДокПРУ = $NumDoC
$xml.Файл.Документ.СвДокПРУ.ИдентДок.ДатаДокПРУ = "$Date"
$xml.Файл.Документ.СвДокПРУ.ДенИзм.КурсВал = $Currency
$xml.Файл.Документ.СвДокПРУ.СодФХЖ1.ЗагСодОпер = $Zagoper
<# почему-то не может зайти в этот блок
$xml.Файл.Документ.СвДокПРУ.СодФХЖ1.Основание.НаимОсн =
$xml.Файл.Документ.СвДокПРУ.СодФХЖ1.Основание.НомОсн=
$xml.Файл.Документ.СвДокПРУ.СодФХЖ1.Основание.ДатаОсн=
$xml.Файл.Документ.СвДокПРУ.СодФХЖ1.Основание.ДопСвОсн=
#>
$xml.Файл.Документ.СвДокПРУ.СодФХЖ1.ИдГосКон = $IDgos
$xml.Файл.Документ.СвДокПРУ.СодФХЖ1.ВидОперации = $ВидОперации

$xml.save($DPRR)

Скрипт пишу в Windows PowerShell ISE. В нем в путях по узлам выводяться подсказки.

например для вот это узла <Основание НаимОсн="Наименование основания 2" НомОсн="454-11" ДатаОсн="04.12.2017" ДопСвОсн="поле для доп. сведений" />

Подсказка выводилась до ветки $xml.Файл.Документ.СвДокПРУ.СодФХЖ1.Основание и для дальнейших узлов НаимОсн, НомОсн и т.д. подсказок не выводилось. Если указать эти узлы вручную, то выводиться сообщение, что не удается найти свойство.

Подозреваю, что дела в глубине расположения узлов в дереве и это можно как то обойти, но к сожалению примеров толковых найти не могу.

greg zakharov 05-12-2017 09:47 2782419

Цитата:

Цитата Bolshoi
Скрипт пишу в Windows PowerShell ISE. В нем в путях по узлам выводяться подсказки.

Лучше поведайте какова конечная цель, что требуется? Просто извлечь данные из некоторого узла? Ну дык есть такая штука, XPath называется, без всяких дурацких ISE извлекается с помощью Select-Xml:
Код:

PS E:\> Select-Xml -Path E:\src\test.xml -XPath "//*[НаимОсн]"

Node                                            Path                                            Pattern
----                                            ----                                            -------
Основание                                      E:\src\test.xml                                //*[@НаимОсн]
Основание                                      E:\src\test.xml                                //*[@НаимОсн]

И далее, по узлу:
Код:

PS E:\> $x = Select-Xml -Path E:\src\test.xml -XPath "//*[НаиОсн]"
PS E:\> $x | % {$_.Node}

НаимОсн                            НомОсн                              ДатаОсн                            ДопСвОсн
-------                            ------                              -------                            --------
Наименование основания 2            454-11                              04.12.2017                          поле для доп. сведений
Наименование основания 2            4нк84                              04.12.2017                          доп сведения оснвоание 2

PS E:\> $x | % {$_.Node.ДопСвОсн}
поле для доп. сведений
доп сведения оснвоание 2

И так далее.

Bolshoi 08-12-2017 15:20 2783199

Цитата:

Цитата greg zakharov
Лучше поведайте какова конечная цель, что требуется? »

Целью является изменение содержимого узлов xml документ рандомными данными и сохранение этих изменениц в тот же документ. Xpath я не понял как работает. А ise давал до определенного момента простой и понятный результат

Bolshoi 17-01-2018 10:58 2791982

Понял как менять. Может это и не очень красиво, но у меня получилось так:
Код:

$File = Get-Content $DPRRpath
$DPRR = [XML]$File

$НомДокПРУ = "/Файл/Документ/СвДокПРУ/ИдентДок[@НомДокПРУ]"
$DPRR.SelectNodes($НомДокПРУ)| % { $_.SetAttribute("НомДокПРУ", "$ЗначНомДокПРУ") }



Время: 00:39.

Время: 00:39.
© OSzone.net 2001-