2012-01-05 50 views
1

我有一些數據,我從註冊表中讀取並希望修改。示例數據如下所示:讀取/修改數據爲散列表或對象

<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

在你有的地方添加一個根標籤,那麼你應該可以把它當作xml。 – EBGreen 2012-01-05 15:22:28

+1

你也可能想擺脫標籤中的空格 – 2012-01-05 15:27:32

+0

@jon Z:是的空間似乎是解析它的問題......但下一個問題是,有兩個根元素? – Remko 2012-01-05 15:31:47

回答

1

一般來說,如果你有要修改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的更多信息,請參閱documentation

UPDATE

再次刪除額外的根文檔,只是用它來得到它作爲一個字符串。

$newWrappedData = $doc.Root.InnerXml 

然後使用StreamWriter或File.CreateText或其他方式保存字符串。

+0

對於本示例爲+1。我想我們還需要在保存之前刪除添加的根節點? – Remko 2012-01-06 20:43:55

+0

我添加了一個更新,以顯示如何檢索xml而不包裝節點。 – Richard 2012-01-06 20:51:10

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 } 
    } 
}