我有一些数据是我从注册表中读取并希望修改的。示例数据如下所示:
<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,但这会产生错误。
答案 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等保存字符串。