none
Сравнение 2 xml файлов.

    Вопрос

  • Добрый день, подскажите пожалуйста, как сравнить 2 файла xml, и вывести информацию о изменении.

    Есть 2 файла, приведу часть файла о продуктах Майкрософт которые пытаюсь сравнить:

    1 файл:

    <?xml version="1.0" encoding="utf-8"?>
    <products updated="4/1/2017">
      <product name="WAC">
        <addresslist type="IPv6">
          <address>2603:1020:201::37</address>
          <address>2603:1020:201::204</address>
        </addresslist>
        <addresslist type="IPv4">
          <address>13.69.187.20/32</address>
          <address>13.70.184.242/32</address>
         </addresslist>
        <addresslist type="URL">
          <address>*broadcast.officeapps.live.com</address>
          <address>*excel.officeapps.live.com</address>
          <address>*onenote.officeapps.live.com</address>
          <address>*powerpoint.officeapps.live.com</address>
          <address>*view.officeapps.live.com</address>
          <address>*visio.officeapps.live.com</address>
          <address>*word-edit.officeapps.live.com</address>
          <address>*word-view.officeapps.live.com</address>
          <address>*.cdn.office.net</address>
        </addresslist>
      </product>
      <product name="Yammer">
        <addresslist type="IPv6">
          <address>2620:1ec:a92::158</address>
          <address>2620:1ec:4::158</address>
          <address>2620:1ec:a92::159</address>
          <address>2620:1ec:4::159</address>
        </addresslist>
        <addresslist type="IPv4">
          <address>13.107.6.158/31</address>
          <address>13.107.9.158/31</address>
          <address>134.170.148.0/22</address>
        </addresslist>
        <addresslist type="URL">
          <address>*.assets-yammer.com</address>
          <address>ajax.googleapis.com</address>
          <address>*.cloudfront.net</address>
          <address>*.yammer.com</address>
          <address>*.yammerusercontent.com</address>
        </addresslist>
      </product>
    </products>

    2 файл, с добавленной новой подсетью

    <address>134.170.255.0/22</address>

    В этом и есть разница:

    <?xml version="1.0" encoding="utf-8"?>
    <products updated="4/1/2017">
      <product name="WAC">
        <addresslist type="IPv6">
          <address>2603:1020:201::37</address>
          <address>2603:1020:201::204</address>
          </addresslist>
        <addresslist type="IPv4">
          <address>13.69.187.20/32</address>
          <address>13.70.184.242/32</address>
         </addresslist>
        <addresslist type="URL">
          <address>*broadcast.officeapps.live.com</address>
          <address>*excel.officeapps.live.com</address>
          <address>*onenote.officeapps.live.com</address>
          <address>*powerpoint.officeapps.live.com</address>
          <address>*view.officeapps.live.com</address>
          <address>*visio.officeapps.live.com</address>
          <address>*word-edit.officeapps.live.com</address>
          <address>*word-view.officeapps.live.com</address>
          <address>*.cdn.office.net</address>
        </addresslist>
      </product>
      <product name="Yammer">
        <addresslist type="IPv6">
          <address>2620:1ec:a92::158</address>
          <address>2620:1ec:4::158</address>
          <address>2620:1ec:a92::159</address>
          <address>2620:1ec:4::159</address>
        </addresslist>
        <addresslist type="IPv4">
          <address>13.107.6.158/31</address>
          <address>13.107.9.158/31</address>
          <address>134.170.148.0/22</address>
          <address>134.170.255.0/22</address>
        </addresslist>
        <addresslist type="URL">
          <address>*.assets-yammer.com</address>
          <address>ajax.googleapis.com</address>
          <address>*.cloudfront.net</address>
          <address>*.yammer.com</address>
          <address>*.yammerusercontent.com</address>
        </addresslist>
      </product>
    </products>


    Выполняю такой командой:

    $a = Get-Content C:\_DISTR\xml_priv\a.xml
    $b = Get-Content C:\_DISTR\xml_new\b.xml
    Compare-Object -ReferenceObject $a -DifferenceObject $b

    Вывод получается таким:

    InputObject                                                 SideIndicator
    -----------                                                 -------------
          <address>134.170.255.0/22</address>                   =>

    Подскажите пожалуйста, как добиться такого чтобы, вывод показывал вот так:

     <product name="Yammer">
        <addresslist type="IPv4">
          <address>134.170.255.0/22</address>
        </addresslist>
     </product>


    Буду благодарен за любую помощь.
    • Изменено new guy 1 14 апреля 2017 г. 11:56
    14 апреля 2017 г. 11:51

Ответы

  • Add-Type -AssemblyName System.Xml.Linq

    $xmla = [xml](Get-Content a.xml) $xmlb = [xml](Get-Content b.xml) Compare-Object $xmla.products.product $xmlb.products.product -Property Name -IncludeEqual | Foreach { $product = $_.Name $fp = "//product[@name='$product']" if($_.SideIndicator -eq "=>") { Write-Host "`n[+] Добавили Product $($_.Name) в файл $file`n" -ForeGround Green [System.Xml.Linq.XElement]::Parse($xmlb.SelectNodes($fp).OuterXml).ToString() } if($_.SideIndicator -eq "<=") { Write-Host "`n[-] Удалили Product $($_.Name) из файла $file`n" -ForeGround Yellow [System.Xml.Linq.XElement]::Parse($xmla.SelectNodes($fp).OuterXml).ToString() } if($_.SideIndicator -eq "==") { $pa = $xmla.SelectNodes($fp) $pb = $xmlb.SelectNodes($fp) Compare-Object $pa.addresslist $pb.addresslist -Property Type -IncludeEqual | Foreach { $type = $_.Type $ft = "$fp//addresslist[@type='$type']" if($_.SideIndicator -eq "=>") { Write-Host "`n[+] Добавили Type $type в файл $file`n" -ForeGround Green $oxml = "<product name=""$product"">{0}</product>" -f $xmlb.SelectNodes($ft).OuterXml [System.Xml.Linq.XElement]::Parse($oxml).ToString() } if($_.SideIndicator -eq "<=") { Write-Host "`n[-] Удалили Type $type из файла $file`n" -ForeGround Yellow $oxml = "<product name=""$product"">{0}</product>" -f $xmla.SelectNodes($ft).OuterXml [System.Xml.Linq.XElement]::Parse($oxml).ToString() } if($_.SideIndicator -eq "==") { $psa = $xmla.SelectNodes($ft) $psb = $xmlb.SelectNodes($ft) Compare-Object $psa.address $psb.address | Group SideIndicator | Foreach { if($_.Name -eq "=>") { Write-Host "`n[+] Добавили Address в файл $file`n" -ForeGround Green $pxml = $_.Group | Foreach {"<product name=""$product""><addresslist type=""$type"">"} { $fa = "$fp//address[contains(text(),'$($_.InputObject)')]" $xmlb.SelectNodes($fa).OuterXml } {"</addresslist></product>"} [System.Xml.Linq.XElement]::Parse($pxml).ToString() } if($_.Name -eq "<=") { Write-Host "`n[-] Удалили Address из файла $file`n" -ForeGround Yellow $pxml = $_.Group | Foreach {"<product name=""$product""><addresslist type=""$type"">"} { $fa = "$fp//address[contains(text(),'$($_.InputObject)')]" $xmla.SelectNodes($fa).OuterXml } {"</addresslist></product>"} [System.Xml.Linq.XElement]::Parse($pxml).ToString() } } } } } }



    • Изменено KazunEditor 14 апреля 2017 г. 17:47
    • Помечено в качестве ответа new guy 1 17 апреля 2017 г. 14:29
    14 апреля 2017 г. 17:45
    Отвечающий

Все ответы

  • Add-Type -AssemblyName System.Xml.Linq

    $xmla = [xml](Get-Content a.xml) $xmlb = [xml](Get-Content b.xml) Compare-Object $xmla.products.product $xmlb.products.product -Property Name -IncludeEqual | Foreach { $product = $_.Name $fp = "//product[@name='$product']" if($_.SideIndicator -eq "=>") { Write-Host "`n[+] Добавили Product $($_.Name) в файл $file`n" -ForeGround Green [System.Xml.Linq.XElement]::Parse($xmlb.SelectNodes($fp).OuterXml).ToString() } if($_.SideIndicator -eq "<=") { Write-Host "`n[-] Удалили Product $($_.Name) из файла $file`n" -ForeGround Yellow [System.Xml.Linq.XElement]::Parse($xmla.SelectNodes($fp).OuterXml).ToString() } if($_.SideIndicator -eq "==") { $pa = $xmla.SelectNodes($fp) $pb = $xmlb.SelectNodes($fp) Compare-Object $pa.addresslist $pb.addresslist -Property Type -IncludeEqual | Foreach { $type = $_.Type $ft = "$fp//addresslist[@type='$type']" if($_.SideIndicator -eq "=>") { Write-Host "`n[+] Добавили Type $type в файл $file`n" -ForeGround Green $oxml = "<product name=""$product"">{0}</product>" -f $xmlb.SelectNodes($ft).OuterXml [System.Xml.Linq.XElement]::Parse($oxml).ToString() } if($_.SideIndicator -eq "<=") { Write-Host "`n[-] Удалили Type $type из файла $file`n" -ForeGround Yellow $oxml = "<product name=""$product"">{0}</product>" -f $xmla.SelectNodes($ft).OuterXml [System.Xml.Linq.XElement]::Parse($oxml).ToString() } if($_.SideIndicator -eq "==") { $psa = $xmla.SelectNodes($ft) $psb = $xmlb.SelectNodes($ft) Compare-Object $psa.address $psb.address | Group SideIndicator | Foreach { if($_.Name -eq "=>") { Write-Host "`n[+] Добавили Address в файл $file`n" -ForeGround Green $pxml = $_.Group | Foreach {"<product name=""$product""><addresslist type=""$type"">"} { $fa = "$fp//address[contains(text(),'$($_.InputObject)')]" $xmlb.SelectNodes($fa).OuterXml } {"</addresslist></product>"} [System.Xml.Linq.XElement]::Parse($pxml).ToString() } if($_.Name -eq "<=") { Write-Host "`n[-] Удалили Address из файла $file`n" -ForeGround Yellow $pxml = $_.Group | Foreach {"<product name=""$product""><addresslist type=""$type"">"} { $fa = "$fp//address[contains(text(),'$($_.InputObject)')]" $xmla.SelectNodes($fa).OuterXml } {"</addresslist></product>"} [System.Xml.Linq.XElement]::Parse($pxml).ToString() } } } } } }



    • Изменено KazunEditor 14 апреля 2017 г. 17:47
    • Помечено в качестве ответа new guy 1 17 апреля 2017 г. 14:29
    14 апреля 2017 г. 17:45
    Отвечающий
  • Добрый вечер, Kazun.

    Благодарю Вас за помощь, спасибо большое !

    17 апреля 2017 г. 14:30
  • Добрый вечер, Александр.

    Благодарю за Вашу помощь, подскажите пожалуйста, пытаюсь отсылать данные изменения в файле, через E-mail сообщение, сообщение доходит в виде:

    Код, который я немного изменил такой:

    	if ($_.Name -eq "=>")
    					{
    						#Write-Host "`n[+] Добавили Address в файл $file`n" -ForeGround Green
    						$pxml = $_.Group | Foreach { "<product name=""$product""><addresslist type=""$type"">" } {
    							$fa = "$fp//address[contains(text(),'$($_.InputObject)')]"
    							$xmlb.SelectNodes($fa).OuterXml
    						} { "</addresslist></product>" }
    						#[System.Xml.Linq.XElement]::Parse($pxml).ToString()
    						
    						$mail_subject = "O365IPAddresses changes: был добавлен Address"
    						$message = "[+] Добавили Address в файл."
    						$message += [System.Xml.Linq.XElement]::Parse($pxml).ToString()
    						$sendmail = $true
    					}

    Отсылку сообщения выполняю командой:

    if ($sendmail)
    	{
    		send-mailmessage -to "E-mail" -from "E-mail" -body $message -subject $mail_subject -bodyashtml -smtpserver test.local -encoding $encoding
    	}

    Подскажите пожалуйста, почему в сообщении я вижу лишь подсеть с маской, а название продукта нет ?

    19 апреля 2017 г. 15:32
  • Такой результат получается при указании параметра -bodyashtml и теги xml, воспринимаются как html. Поэтому либо убрать этот параметр или экранировать, или смотреть код письма в html.

    Add-Type -AssemblyName System.Web
    $message = [Web.HttpUtility]::HtmlEncode($message).split("`n") | Foreach {"$_<br>" -replace " ","&nbsp;"}

    19 апреля 2017 г. 16:18
    Отвечающий
  • Добрый день, Александр.

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

    Хорошего дня.

    22 ч. 34 мин. назад
  • Добавить после $type=$_.Type, оператор if ($type -ne "IPV6"), где идет сравнение, какие типы должны участвовать IPV4,IPV6 или URL.

    Можно сделать фильтр , после:

    Compare-Object $pa.addresslist $pb.addresslist -Property Type -IncludeEqual  | Where-Object {$_.Type -ne "IPV6"}

     
    • Изменено KazunEditor 20 ч. 38 мин. назад
    20 ч. 42 мин. назад
    Отвечающий