【问题标题】:Search/Replace XML via Powershell通过 Powershell 搜索/替换 XML
【发布时间】:2020-08-24 08:25:56
【问题描述】:

我正在寻找一种方法来通过 XML 文档搜索“ID”标签中的特定 ID,然后找到下一个标签并将其值替换为“true”。 ID 将由 csv 文件的第一列提供。以下是 XML 结构的示例:

<primary>
<main>
<id>47</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
<primary>
<main>
<id>48</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
<primary>
<main>
<id>49</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
<primary>
<main>
<id>50</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
<primary>
<main>
<id>51</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>

现在想象一下 csv 文件在第 1 列中有:

47
49

我只想将那些指示标志标记更新为 true。
任何帮助将不胜感激!

【问题讨论】:

  • 为了清楚起见:当我说“下一个标签”时,我指的是下一个 标签。我尝试了正则表达式查找和替换,但它选择了整个文档中的最后一个 标记,而不是与定位 ID 相同的 标记中的那个标记
  • 您的 XML 无效,因为它缺少根元素。此外,带有要查找的 id 的 csv 看起来像一个简单的文本文件,其中每个 id 都在一个新行上。这是文件的实际格式吗?
  • 是的,正是这种格式

标签: xml powershell replace find


【解决方案1】:

第一件事:不要在 xml 上使用正则表达式替换。 PowerShell 非常能够处理(有效的)XML。

如评论所述,您显示的 XML 无效,因为它缺少根元素。
通过将 XML 全部包含在 &lt;root&gt;...&lt;/root&gt; 元素中来修复 XML 后,您可以这样阅读:

[xml]$xml = Get-Content -Path 'D:\Test\input.xml' -Raw

接下来,读取文件以获取要更新的 id。如果这个文件就像你向我们展示的那样,一个文本文件,其中每个 id 都在自己的新行上,使用这个:

$ids = Get-Content -Path 'D:\Test\ids.txt'

但是,如果此文件 IS 是 CSV 文件,则类似于

“身份证”,“某事” “47”,“随便” “49”,“任何东西”

然后使用以下命令将 id 作为数组读取:

$ids = (Import-Csv -Path  'D:\Test\ids.csv').ID

您现在可以遍历 id 并更改所属 &lt;indicatorflag&gt; 标签的值:

foreach ($id in $ids) {
    ($xml.root.primary.main | Where-Object {$_.id -eq $id}).indicatorflag = 'true'
}

# save the updated XML
$xml.Save('D:\Test\output.xml')

【讨论】:

  • 非常感谢!这一切都说得通。我现在就试一试
【解决方案2】:

您可以使用以下 XPath 表达式来查找 &lt;indicatorflag&gt; 节点,它是 &lt;id&gt;49&lt;/id&gt; 节点之后的兄弟节点:

//id[. = 49]/following-sibling::indicatorflag

泛化并使用Select-XmlXmlDocument.SelectSingleNode()方法获取节点:

$xml = [xml]@'
<root>
<primary>
<main>
<id>48</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
<primary>
<main>
<id>49</id>
<desc>foobar</desc>
<indicatorflag>false</indicatorflag>
</main>
</primary>
</root>
'@

foreach($ID in 48,49){
  $ifNode = $xml.SelectSingleNode("//id[. = $ID]/following-sibling::indicatorflag")
  if($ifNode){
    $ifNode.InnerText = "false"
  }
}

$xml.Save("C:\path\to\output.xml")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-11-28
    • 1970-01-01
    • 2021-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多