Он повреждает файл 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 .+)\[\](?=>)')
)