Чтение / изменение данных как хеш-таблицы или объекта - PullRequest
1 голос
/ 05 января 2012

У меня есть некоторые данные, которые я читаю из реестра и хочу изменить.Пример данных выглядит следующим образом:

<User Blob>
    <Item>
        <Key>SomeKey</Key>
        <Value>false</Value>
    </Item>
    <Item>
        <Key>AnotherKey</Key>
        <Value></Value>
    </Item>
</User Blob>
<Primary Server Blob>
    <Item>
        <Key>Just a key</Key>
        <Value></Value>
    </Item>
    <Item>
        <Key>And another key</Key>
        <Value>true</Value>
    </Item>
</Primary Server Blob>

Я хочу иметь возможность изменить значение определенного ключа.Например:

User Blob.SomeKey = $true

Я пытался преобразовать данные в XML или в HashTable, но это приводит к ошибкам.

Ответы [ 2 ]

1 голос
/ 07 января 2012

Как правило, если у вас есть данные XML, которые вы хотите изменить (а не просто прочитать), и данные имеют достаточно маленький размер (чтобы не загружать массивные объекты в память), вам следует использовать документ некоторого Добрый. Из-за его способности использовать XPath, я бы порекомендовал XmlDocument. (XPath упрощает проблему такого рода.)

Как вы правильно заметили, вам понадобится один корень XML. Это легко решить, просто поместите все данные, которые у вас есть, в другой корневой узел.

Итак, вот код, который должен помочь.

$data = @"
<UserBlob>
    <Item>
        <Key>SomeKey</Key>
        <Value>false</Value>
    </Item>
    <Item>
        <Key>AnotherKey</Key>
        <Value></Value>
    </Item>
</UserBlob>
<PrimaryServerBlob>
    <Item>
        <Key>Just a key</Key>
        <Value></Value>
    </Item>
    <Item>
        <Key>And another key</Key>
        <Value>true</Value>
    </Item>
</PrimaryServerBlob>
"@

$wrappedData = "<root>$data</root>"
$doc = new-object Xml.XmlDocument
$doc.LoadXml($wrappedData)
$nodeToChange = $doc.SelectSingleNode("/root/UserBlob/Item[Key='SomeKey']")
if($nodeToChange){
    $nodeToChange.Value = "NEW VALUE"
}
$doc.Save("[PATH_TO_OUTPUT_FILE]")

Я упустил обработку ошибок и правильное удаление объектов для краткости. Я оставлю это на ваше усмотрение. : -)

Для получения дополнительной информации о XmlDocument см. Документацию .

UPDATE

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

$newWrappedData = $doc.Root.InnerXml

Затем сохраните строку, используя StreamWriter или File.CreateText или что-то еще.

1 голос
/ 05 января 2012

Я получил его для работы с кодом ниже, обратите внимание, что я использую XMLReader, потому что он может обрабатывать несколько корневых элементов, установив для ConformanceLevel значение Fragment. Если есть лучшие решения, пожалуйста, добавьте их как ответ ...

$readerSettings = New-Object System.Xml.XmlReaderSettings
$readerSettings.ConformanceLevel = [System.Xml.ConformanceLevel]::Fragment

$reader = [system.Xml.XmlReader]::Create("MyXML.xml", $readerSettings)
while ($reader.Read())
{
    switch ($reader.NodeType)
    {
        "Element"
        {
            $numAttributes = $reader.AttributeCount
            $nodeName = $reader.Name
            "nodeName = {0}" -f $nodeName
            for ($i = 0 ; $i -lt $numAttributes ; $i++)
            {
                $attributeValue = $reader.GetAttribute($i)
                "`tattributeValue = {0}" -f $attributeValue
            }

            break
        }
        "Text"
        {
            $xmlNodeText = $reader.Value
            "`txmlNodeText = {0}" -f $xmlNodeText
            break
        }
        "EndElement" 
        {
            $xmlNodeText = [String]::Empty
            break
        }

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