XML递归节点添加
XML recursive node adding
我正在为在 Powershell 中向 XML 递归添加子节点而苦苦挣扎。
主要目标是根据提供的文件更新 XML 文件。
例如。
XML 看起来像这样:
<a>
<b>
<c1>Value0</c1>
</b>
</a>
我想添加带有子节点的节点,使其看起来像这样(顺序不重要):
<a>
<b>
<c>
<d1>Value1</d2>
<d2>Value2</d2>
<d3>Value3</d3>
</c>
<c1>Value0</c1>
</b>
</a>
我为此创建了两个函数:
function InsertRecursively {
param (
$OriginalXml,
$DataToInsert
)
foreach ($key in $DataToInsert.Keys) {
if ($DataToInsert.$key.GetType().Name -eq "Hashtable") {
SetChildItem -XML $OriginalXml -ChildName $key
InsertRecursively -OriginalXml $OriginalXml.$key -DataToInsert $DataToInsert.$key
}
else {
SetChildItem -Xml $OriginalXml -ChildName $key -ChildValue $DataToInsert.$key
}
}
}
function SetChildItem {
param (
$Xml,
$ChildName,
$ChildValue
)
if ($null -eq $Xml.$ChildName) {
$child = $ssCont.CreateElement($ChildName)
if ($ChildValue) {
$child.InnerText = $ChildValue.ToString()
}
$Xml.AppendChild($child) > $null
Write-Host "Adding item '$ChildName'"
}
elseif (($null -ne $ChildValue) -and ($Xml.$ChildName -ne $ChildValue)) {
$Xml.$ChildName = $ChildValue.ToString()
Write-Host "Updating value of item '$ChildName'"
}
else {
Write-Host "Item '$ChildName' is set correctly"
}
return $Xml
}
当函数将第一个子节点添加到现有节点时一切正常,问题是当函数想要将另一个子节点添加到该子节点时 - 那么 SetChildItem 函数中的 $Xml 参数只是一个空字符串,而不是函数可以添加子节点的节点。结果报错,字符串不包含方法AppendChild.
以下是我在 C# 中使用 Xml Linq 的方法。您可以将 Xml Linq 库与 Power Shell.
一起使用
string input = @"
<a>
<b>
<c1>Value0</c1>
</b>
</a>";
XDocument doc = XDocument.Parse(input);
XElement nodeB = doc.Descendants("b").FirstOrDefault();
XElement nodeC = new XElement("c", new object[] {
new XElement("d1", "Value1"),
new XElement("d2", "Value2"),
new XElement("d2", "Value3")
});
nodeB.Add(nodeC);
如果你想将新节点作为第一项使用:nodeB.AddFirst(nodeC);
像下面这样更简单的东西:
$xml = [xml]@"
<a>
<b>
<c1>Value0</c1>
</b>
</a>
"@
$newElements = [xml]@"
<c>
<d1>Value1</d1>
<d2>Value2</d2>
<d3>Value3</d3>
</c>
"@
$newNode = $xml.ImportNode($newElements.get_DocumentElement(), $true)
$xml.SelectSingleNode('//b').AppendChild($newNode)
应该输出
<a>
<b>
<c1>Value0</c1>
<c>
<d1>Value1</d1>
<d2>Value2</d2>
<d3>Value3</d3>
</c>
</b>
</a>
我正在为在 Powershell 中向 XML 递归添加子节点而苦苦挣扎。 主要目标是根据提供的文件更新 XML 文件。
例如。 XML 看起来像这样:
<a>
<b>
<c1>Value0</c1>
</b>
</a>
我想添加带有子节点的节点,使其看起来像这样(顺序不重要):
<a>
<b>
<c>
<d1>Value1</d2>
<d2>Value2</d2>
<d3>Value3</d3>
</c>
<c1>Value0</c1>
</b>
</a>
我为此创建了两个函数:
function InsertRecursively {
param (
$OriginalXml,
$DataToInsert
)
foreach ($key in $DataToInsert.Keys) {
if ($DataToInsert.$key.GetType().Name -eq "Hashtable") {
SetChildItem -XML $OriginalXml -ChildName $key
InsertRecursively -OriginalXml $OriginalXml.$key -DataToInsert $DataToInsert.$key
}
else {
SetChildItem -Xml $OriginalXml -ChildName $key -ChildValue $DataToInsert.$key
}
}
}
function SetChildItem {
param (
$Xml,
$ChildName,
$ChildValue
)
if ($null -eq $Xml.$ChildName) {
$child = $ssCont.CreateElement($ChildName)
if ($ChildValue) {
$child.InnerText = $ChildValue.ToString()
}
$Xml.AppendChild($child) > $null
Write-Host "Adding item '$ChildName'"
}
elseif (($null -ne $ChildValue) -and ($Xml.$ChildName -ne $ChildValue)) {
$Xml.$ChildName = $ChildValue.ToString()
Write-Host "Updating value of item '$ChildName'"
}
else {
Write-Host "Item '$ChildName' is set correctly"
}
return $Xml
}
当函数将第一个子节点添加到现有节点时一切正常,问题是当函数想要将另一个子节点添加到该子节点时 - 那么 SetChildItem 函数中的 $Xml 参数只是一个空字符串,而不是函数可以添加子节点的节点。结果报错,字符串不包含方法AppendChild.
以下是我在 C# 中使用 Xml Linq 的方法。您可以将 Xml Linq 库与 Power Shell.
一起使用 string input = @"
<a>
<b>
<c1>Value0</c1>
</b>
</a>";
XDocument doc = XDocument.Parse(input);
XElement nodeB = doc.Descendants("b").FirstOrDefault();
XElement nodeC = new XElement("c", new object[] {
new XElement("d1", "Value1"),
new XElement("d2", "Value2"),
new XElement("d2", "Value3")
});
nodeB.Add(nodeC);
如果你想将新节点作为第一项使用:nodeB.AddFirst(nodeC);
像下面这样更简单的东西:
$xml = [xml]@"
<a>
<b>
<c1>Value0</c1>
</b>
</a>
"@
$newElements = [xml]@"
<c>
<d1>Value1</d1>
<d2>Value2</d2>
<d3>Value3</d3>
</c>
"@
$newNode = $xml.ImportNode($newElements.get_DocumentElement(), $true)
$xml.SelectSingleNode('//b').AppendChild($newNode)
应该输出
<a>
<b>
<c1>Value0</c1>
<c>
<d1>Value1</d1>
<d2>Value2</d2>
<d3>Value3</d3>
</c>
</b>
</a>