读取/修改数据作为哈希表或对象

时间:2012-01-05 15:11:59

标签: xml powershell

我有一些数据是我从注册表中读取并希望修改的。示例数据如下所示:

<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 个答案:

答案 0 :(得分:1)

我使用下面的代码,请注意我使用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 }
    }
}

答案 1 :(得分:1)

通常,如果你有想要修改的XML数据(不仅仅是读取),并且数据的大小足够小(为了避免将大量对象加载到内存中),你可能希望使用一些Document类。由于它能够使用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的详细信息,请参阅documentation

<强>更新

要再次删除其他根文档,只需使用此文档将其作为字符串。

$newWrappedData = $doc.Root.InnerXml

然后使用StreamWriter或File.CreateText等保存字符串。