从大型xml文件中删除节点的平台无关的powershell方法是什么?



我有90mb的xml文件,我想在Linux Mac上处理&窗户他们有数百种"标签"像这样的节点:

<net.rptools.maptool.model.Label> ...few children... </net.rptools.maptool.model.Label>

我想处理文件以删除所有这些Label节点。然而,最好是把他们的父母,这似乎是一些

<labels class="linked-hash-map"> ...many megs of Label children... </labels>

我不知道哪个更好,直到我尝试将xml加载回应用程序。

我见过一些powershell XML处理的例子,它们似乎使用了Windows特定的api。从大型文件中删除节点时,首选的与平台无关的API和样式是什么?

如果您不想要任何花哨的api,只是将xml作为对象进行普通访问,那么只需将xml转换为[xml]对象即可

$xmldoc = [xml](Get-Content 'c:tempbooks.xml' -Raw)

$xmldoc = [xml]@"
<?xml version="1.0"?>
<catalog>
<book id="bk101">
<author>Gambardella, Matthew</author>
<title>XML Developer's Guide</title>
<genre>Computer</genre>
<price>44.95</price>
<publish_date>2000-10-01</publish_date>
<description>An in-depth look at creating applications 
with XML.</description>
</book>
<book id="bk102">
<author>Ralls, Kim</author>
<title>Midnight Rain</title>
<genre>Fantasy</genre>
<price>5.95</price>
<publish_date>2000-12-16</publish_date>
<description>A former architect battles corporate zombies, 
an evil sorceress, and her own childhood to become queen 
of the world.</description>
</book>
</catalog>
"@

然后你可以通过它的属性

访问或修改xml
PS C:temp> $xmldoc.catalog.book
id           : bk101
author       : Gambardella, Matthew
title        : XML Developer's Guide
genre        : Computer
price        : 44.95
publish_date : 2000-10-01
description  : An in-depth look at creating applications
with XML.
id           : bk102
author       : Ralls, Kim
title        : Midnight Rain
genre        : Fantasy
price        : 5.95
publish_date : 2000-12-16
description  : A former architect battles corporate zombies,
an evil sorceress, and her own childhood to become queen
of the world.

如果你修改了,你可以使用

将修改过的对象写回文件
$xmldoc.Save("C:temptestout.xml")

我选择了下面的例子。应用程序不允许我删除"标签"。net.rptools.maptool.model.Label"节点是"entry"的子节点。节点。因此,我使用带有XPath表达式的SelectNodes来查找所有"条目"。"标签"下的节点父目录,然后从父目录中删除它们:

#!/usr/bin/env pwsh
Set-StrictMode -Version Latest

$branch = Get-Location 
$contentFileIn = "$branchcontent.xml"
$contentFileOut = "$branchcontent_pruned.xml"
$xmlDoc = [xml]::new()
$xmlDoc.Load($contentFileIn)
$entryNodes = $xmlDoc.SelectNodes("//labels/entry")
foreach ($entryNode in $entryNodes){
$entryNode.ParentNode.RemoveChild($entryNode)
}
$xmldoc.Save($contentFileOut)

使用XSLT很容易删除具有给定名称的元素,XSLT几乎是与平台无关的。在XSLT 3.0中,它很简单:

<xsl:transform version="3.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:mode on-no-match="shallow-copy"/>
<xsl:template match="label"/>
</xsl:transform>

XSLT 1.0更广泛使用,但稍微冗长一些:

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
<xsl:copy><xsl:apply-templates/></xsl:copy>
</xsl:template>
<xsl:template match="label"/>
</xsl:transform>

通过解释,在这两种情况下,您都在说默认情况下,元素被递归地浅复制到结果,除了标签元素,它不生成输出(即它们被删除)。

最新更新