Save () в powershell повреждает файл xml - PullRequest
1 голос
/ 31 марта 2020

У меня есть простой файл xml, в котором при использовании get-content и сохранении файла xml обратно. Это повреждает файл xml и становится непригодным для использования. Мы приветствуем вашу помощь / предложение / решения.

$xmlfile = 'C:\Test\stack.xml'
[xml]$xmlcontent = (Get-Content $xmlfile)
$xmlcontent.Save($xmlfile)

Ниже приведен мой пример файла xml, который я использую здесь в моем случае для запуска моего скрипта powershell, упомянутого выше. Вы можете сохранить ниже xml в файле для ссылки.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE fccconfig SYSTEM "fccconfig.dtd">

<fccconfig version="1.2.3">
   <fccdefaults>

      <!-- general -->
      <property name="FCC_CacheLocation" value="C:/Users/Public/sometestCache" overridable="true"/>
      <property name="FCC_LogFile" value="C:/Users/Public/sometestfile.log" overridable="true" />
      <!-- external site access definition -->
      <!-- <site id="013B998A65427E" overridable="true"> -->
         <!-- <parentfsc address="localhost:4567" priority="0"/> -->
         <!-- <parentfsc address="myserverhost:4444" priority="1"/> -->
         <!-- <assignment mode="parentfsc" /> -->
      <!-- </site> -->

      <site id="-987654321" overridable="true">
         <parentfsc address="http://testlink:12345/" priority="0" />
      </site>
      <!--__ANT_MARK__-->

   </fccdefaults>

   <!-- default parentfsc - this is a marker that will be overwritten by the installer -->
   <parentfsc address="address1.com:2020" priority="0" transport="lan"/>
   <parentfsc address="address1.com:2020" priority="1" transport="lan"/>

</fccconfig>

Во 2-ом из xml после запуска скрипта добавляются неизвестные персонажи [] . А также изменяется интервал между файлами xml. Ниже приведен фрагмент разницы в файлах. enter image description here

Ответы [ 2 ]

0 голосов
/ 31 марта 2020

Он повреждает файл xml и становится непригодным для использования.

Там нет повреждение - файл все еще может быть прочитан Процессор XML и имеет такое же содержимое , но аспект его форматирования изменился из-за (по умолчанию) поведения, встроенного в System.Xml.XmlDocument класс (доступен через ускоритель типов [xml] в PowerShell):

  • (a) Незначительный пробел во входном тексте XML был обрезан при чтении, и при сохранении элементы были довольно напечатаны (автоматически распределяются по нескольким строкам с отступом); в результате изменилась структура документа visual (но не его содержимое).

  • (b) [] было добавлено в конец объявление типа документа (<!DOCTYPE ...[]>) для обозначения пустого внутреннего подмножества , которое, по-видимому, неизменно добавляется при сохранении документа в файл - опять же, в * 1037 нет никаких изменений содержимое с точки зрения разбора XML.

  • (c) В сохраненном файле используется кодировка символов UTF-8 с спецификацией - независимо от есть ли у входного файла спецификация или нет; причина в атрибуте encoding="UTF-8" в объявлении XML, что (к сожалению) заставляет метод .Save() использовать спецификацию; будучи избыточным, он снова не должен создавать проблем для любого анализатора XML.

    • К сожалению, это избыточное поведение не изменится в интересах обратной совместимости - см. этого GitHub проблема .

Адресация (а) - сохранение исходной визуальной структуры - довольно проста:

$xmlfile = 'C:\Test\stack.xml'

# Create an empty XmlDocument instance...
$xmlcontent = [xml]::new()
# ... and tell it to preserve non-significant whitespace when 
#     reading from / writing to a file.
$xmlcontent.PreserveWhitespace = $true

# Load the XML text from the file.
$xmlContent.Load($xmlFile)

# ...

# Save it back to the file, with the original whitespace preserved.
$xmlcontent.Save($xmlfile)

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


Если вам действительно нужны адреса (b) и (c), выполните следующую команду после вышеуказанного:

[IO.File]::WriteAllText(
  $xmlfile,
  ((Get-Content -Raw $xmlfile) -replace '(?m)(?<=^<!DOCTYPE .+)\[\](?=>)')
)
0 голосов
/ 31 марта 2020

Текст всегда будет лучше, чем картинки. Квадратные скобки, добавленные в строке 2, кажутся обычной xml вещью: Как избавиться от квадратных скобок [] после редактирования и сохранения XML файла

Обратите внимание, что файл будет сохранен с кодировкой в ​​строке 1. В этом случае будет добавлена ​​бомба utf8, если ее там не было.

Возможно, предотвратить переформатирование? Запись в xml не сохраняет форматирование?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...