Как прочитать .xml в память и записать тот же результат

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

PS H:\src\tws> type .\test000.xml
<?xml version="1.0"?>
<eventRuleSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules"
              xsi:schemaLocation="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules/EventRules.xsd">
    <eventRule name="PW-TEST001" ruleType="filter" isDraft="no">
        <description>Paul's test001</description>
    </eventRule>
</eventRuleSet>

Вот простой код, который я использую для его чтения и записи.

PS H:\src\tws> Get-Content .\con000.ps1
$x = [xml](Get-Content -Path .\test000.xml)
$x | Export-Clixml -Path .\con000.xml -Encoding utf8

На выходе есть разделы и. Это почему? Я хотел бы узнать, что вошло. Меня не волнуют символы новой строки или использование HTML-сущностей. Я просто хочу, чтобы контент был семой. Да, план состоит в том, чтобы прочитать шаблон, изменить некоторые значения и вывести новый файл .xml. Это будет введено в планировщик рабочих нагрузок IBM / HCS.

PS H:\src\tws> type .\con000.xml
<Objs Version="1.1.0.1" xmlns="http://schemas.microsoft.com/powershell/2004/04">
  <XD>&lt;?xml version="1.0"?&gt;&lt;eventRuleSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules" x
si:schemaLocation="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules/EventRules.xsd"&gt;&lt;eventRule
name="PW-TEST001" ruleType="filter" isDraft="no"&gt;&lt;description&gt;Paul's test001&lt;/description&gt;&lt;/eventRule&gt;&lt;/eventRuleSet&gt;</XD>
</Objs>
1
0
325
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий
  • Назначение Export-CliXml состоит в том, чтобы сериализовать произвольные объекты для более позднего десериализация через Import-CliXml, используя представление наилучшего усилия в отношении сохранения определенных типов ввода для более поздней «регидратации» через Import-CliXml.

  • Его цель - нет для записи текстовое представление произвольных документов [xml] в файл.

Чтобы сохранить текстовое представление экземпляра [xml] в файл, у вас есть два основных варианта:

  • Если конкретное форматирование текстового представления XML-документа не имеет значения, просто вызовите .OuterXml на (модифицированном) экземпляре [xml] и отправьте его в файл - либо через Set-Content, либо через Out-File / >, но обратите внимание на разные кодировки символов по умолчанию, применяемые этими командлетами в Windows PowerShell.

  • Используйте .NET Framework, если вы хотите, чтобы текстовое представление красиво напечатанный XML в выходном файле:

    • Метод [xml] типа .Save() удобно выполняет неявную красивую печать при сохранении в файл, но есть подводные камни:

      • Поскольку .NET обычно имеет другое представление о текущем каталоге, не забудьте передать полный путь к файлу.

      • В отсутствие объявления XML с атрибутом encoding метод создает файл UTF-8 без спецификации (что предпочтительно с точки зрения кроссплатформенности).

      • Любопытно, что наоборот, если присутствует XML-объявление с encoding="UTF-8"является, результирующий файл будет UTF-8 с участием a BOM, начиная с .NET Core 2.1 / .NET v4.7; см. эта проблема GitHub.

    • Используйте экземпляр [System.Xml.XmlWriter] с явно созданным объектом файлового потока, что является более громоздким, но дает вам контроль над особенностями красивого печатного формата.


Вот простой пример с .OuterXml:

# Read the input file into an XML document (in-memory DOM).
$x = [xml] (Get-Content -Raw ./test000.xml)

# Make updates to the in-memory document
$x.eventRuleSet.eventRule.description = 'new description'

# Save the modified document as text to an output file,
# using the un-prettied textual representation provided by the .OuterXml
# property.
# If *BOM-less* UTF-8 encoding is what you want, simply use
#   $x.Save("$PWD/con000.xml")
# In PowerShell *Core*, you'd get BOM-less UTF-8 even with the command below.
$x.OuterXml | Set-Content -Encoding utf8 ./con000.xml

Примечание об использовании Спецификация (также известной как подпись Unicode) с UTF-8 и другими кодировками Unicode:

  • В Windows PowerShell-Encoding utf8неизменно создает спецификацию (применяется не только к Set-Content, но и к другим командлетам, которые производят вывод файла, например Out-File и Export-Csv).

    • Для создания файлов BOM-меньше UTF-8 требуется прямое использование платформы .NET (для удобной для PowerShell функции оболочки см. Мой этот ответ). Обратите внимание, что кодировка по умолчанию платформы .NET всегда была UTF-8 без спецификации.
  • PowerShell Основной создает файлы BOM-меньше UTF-8 по умолчанию (а также при явном использовании
    -Encoding utf8); вы можете выбрать создание спецификации с помощью -Encoding utf8BOM.

Для наилучшей общей совместимости спецификации в файлах UTF-8 должны иметь вид избегали: платформы Unix и утилиты наследия Unix, также используемые на платформах Windows, обычно не знают, как с ними обращаться.

Точно так же следует избегать -Encoding UTF7, потому что это не стандартная кодировка Unicode (и записывается как без как спецификация в обеих редакциях PowerShell).

В выпусках PowerShell оба все другие кодировки Unicode, доступные с -Encodingделать, создают (соответствующую кодировке) спецификацию: Unicode (UTF-16LE), bigendianunicode (UTF-16BE) и utf32 (UTF-32).

Поэкспериментируйте с этим кодом в отладчике.

$data1 = @"
<?xml version="1.0"?>
<eventRuleSet xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xmlns="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules"
              xsi:schemaLocation="http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules http://www.ibm.com/xmlns/prod/tws/1.0/event-management/rules/EventRules.xsd">
    <eventRule name="PW-TEST001" ruleType="filter" isDraft="no">
        <description>Paul's test001</description>
    </eventRule>
</eventRuleSet>
"@

$xml1 = [xml]$data1

"`n-------data1"
$data1

"`n--------xml1"
$xml1

"`n--------save to file xml2"
$xml1.Save('d:\test\xml2.xml')

$file2 = Get-Content 'd:\test\xml2.xml'
$xml2 = [xml]$file2

"`n--------file2"
$file2

"`n--------edit"
$xml2.eventRuleSet.eventRule.name = "Hello world!"

"`n--------save to file xml3"
$xml2.Save('d:\test\xml3.xml')

$file3 = Get-Content 'd:\test\xml3.xml'

"`n--------file3"
$file3

Другие вопросы по теме