如何使用 vbscript 删除 XML 文件中的特定节点

Posted

技术标签:

【中文标题】如何使用 vbscript 删除 XML 文件中的特定节点【英文标题】:How can I delete a specific node within a XML file by using vbscript 【发布时间】:2010-09-15 11:31:48 【问题描述】:

我遇到的问题是我无法选择需要删除的特定 XML 节点。我已经尝试使用适用于某些 XML 文件的 XPath 来选择节点,但我无法为更复杂的文件中的节点找出正确的 XPath。

有没有人知道可以加载 XML 文件的免费软件工具,以便用户可以选择特定节点并接收准确的 XPath,而无需在路径中进行枚举?

/root/anything[2]

如果没有用于此操作的免费软件工具,有人知道我如何选择所需节点的另一种方法吗?

XML 示例:

根节点: SmsFormData

属性: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/ XMLSchema" FormatVersion="1.0" xmlns="http://schemas.microsoft.com/SystemsManagementServer/2005/03/ConsoleFramework"

子节点:表单

属性: Id="some GUID" CustomData="Some data" FormType="some type" ForceRefresh="false"

子/子节点:页面

子/子/子节点:页面

属性: VendorId="VendorName" Id="some GUID" Assembly="dll File name" Namespace="some Namespace" Type="some Type" HelpID="">

我选择这个特定页面的 xPath 表达式现在是:

xPath = /SmsFormData/Form/Pages/Page[@Id="some Guid"]

要进行选择,我使用以下 vbscript 代码:

Set objDOM = CreateObject("Msxml2.DOMDocument.4.0") 
objDOM.async = false            
objDOM.load(file)       
set objNode = objDOM.selectSingleNode(xPath)

现在的问题是objNode 对象是空的。节点没有被选中,为什么?

【问题讨论】:

您尝试使用的 xml 示例怎么样? 【参考方案1】:

这是一个默认命名空间问题。加载 XML 后尝试包含以下代码:

objDom.SetProperty "SelectionNamespaces", "xmlns:cf=""http://schemas.microsoft.com/SystemsManagementServer/2005/03/ConsoleFramework"""

然后在 XPath 中使用 cf 前缀,例如:

objDom.SelectSingleNode("/cf:SmsFormData/cf:Form/cf:Pages/cf:Page[@Id='Some Guid']")

虽然这可能看起来有点古怪,但这是故意的行为。查看http://support.microsoft.com/kb/288147 了解更多信息,您可能会发现http://msdn.microsoft.com/en-us/library/ms950779.aspx 也很有用。

【讨论】:

【参考方案2】:

感谢您的快速回复!这在简单的情况下肯定有效,但在我的具体情况下不起作用:(

因此,让我们进入细节:

根节点: SmsFormData

属性: xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/ XMLSchema" FormatVersion="1.0" xmlns="http://schemas.microsoft.com/SystemsManagementServer/2005/03/ConsoleFramework"

子节点:表单

属性: Id="some GUID" CustomData="Some data" FormType="some type" ForceRefresh="false"

子/子节点: 页数

子/子/子节点:页面

属性: VendorId="VendorName" Id="some GUID" Assembly="dll File name" Namespace="some Namespace" Type="some Type" HelpID="">

我选择这个特定页面的 xPath 表达式现在是:

xPath = "/SmsFormData/Form/Pages/Page[@Id="some Guid"]"

要进行选择,我使用以下 vbscript 代码:

Set objDOM = CreateObject("Msxml2.DOMDocument.4.0") 

objDOM.async = false        
objDOM.load(file)       

set objNode = objDOM.selectSingleNode(xPath) 

现在的问题是 objNode 对象是空的。节点没有被选中,为什么?

哦,顺便说一句:感谢 Visual XPath 提示!我尝试过使用它,但不幸的是它采用枚举方式:/

【讨论】:

您真的应该编辑您的问题以包含这些详细信息【参考方案3】:

您需要将选择语言设置为 XPath 使用

objDOM.SetProperty "SelectionLanguage", "XPath"

一旦你设置了这个属性,你就可以使用完整的 XPath 来访问你想要的任何元素

【讨论】:

【参考方案4】:

如果您有 Firefox 浏览器,您可以简单地安装 DOM Inspector(仅 Firefox 3.0 需要)和 XPather 扩展。然后,您可以在 DOM Inspector 窗口中遍历到您想要的节点,相应的 XPath 将显示在同一窗口的 XPather 工具栏中。

DOM 检查员:https://addons.mozilla.org/en-US/firefox/addon/6622

XPather:https://addons.mozilla.org/en-US/firefox/addon/1192?id=1192

XPather 似乎尽可能使用属性(而不是枚举)来识别节点(至少这是我在小实验中发现的......)。 希望对您有所帮助...

【讨论】:

【参考方案5】:

给定以下 XML:

<root>
  <anything foo="bar">value1</anything>
  <anything foo="qux">value2</anything>
</root>

...您可以使用 XPath 表达式获取第二个任何节点的值:

/root/anything[@foo="qux"]

(因此,您使用 @property="value" 作为选择器,而不是编号索引)。

至于自动生成此类查询的工具,恰如其分地命名为 Visual XPath 应该可以解决问题,而且它是免费的(它甚至带有 C# 源代码)。

编辑,在海报跟进之后:这种形式的 XPath 选择适用于“简单案例”,就像它适用于最复杂的文档一样。当然,您确实必须确保您的 XPath 表达式是正确的,尽管 Visual XPath 确实会使用数字索引,但它至少为您提供了表达式的其余部分,并且您可以轻松地替换 @ property="value" 选择数字,并测试结果。

鉴于上面的 XML 示例,这个 VBscript:

objDOM.selectSingleNode("/root/anything[@foo=""qux""]/text()").nodeValue

...返回字符串“value2”:根据您的需要,您可能需要稍作调整(同样,Visual XPath 之类的工具或任何好的XPath reference 都会帮助您)。

【讨论】:

【参考方案6】:

嗯,...我的印象是问题必须基于文件。 即使我为 SelectionLanguage 设置了属性,并且如果我使用枚举的 XPath(我通过使用 FireFox XPather 获得),节点对象仍然是空的。

有人知道可能出了什么问题吗?该 xml 文件带有 Microsoft 应用程序,因此应该是有效的。至少我在打开文件或在应用程序中使用它时没有任何问题,所以语法应该没问题。

或者也许有人有一个 vbscript 函数,它遍历整个 xml 文件以找到所需的节点以删除它?

【讨论】:

请停止添加答案,就像这是论坛讨论一样,*** 有不同的范例。【参考方案7】:

你的问题是你有一个默认的命名空间。 XPaths 默认名称空间始终是“无名称”名称空间。

你需要:-

sNamespaces = "xmlns:cf='http://schemas.microsoft.com/SystemsManagementServer/2005/03/ConsoleFramework'"
objDOM.setProperty "SelectionNamespaces", sNamespaces

现在您可以在 XPath 中使用:-

xPath = "/cf:SmsFormData/cf:Form/cf:Pages/cf:Page[@Id=""some Guid""]"

【讨论】:

也谢谢您,但括号需要删除。 -> objDOM.setPropery "SelectionNamespaces", sNamespaces【参考方案8】:

不确定它是否对你有用,但我遇到了类似的问题。

我有一个需要管理的应用程序生成的 XML 文件。它的格式为: <LoginData> <GeneralData> <LoginMask>65537</LoginMask> </GeneralData> <UserData> <User> <Username>TEST0</Username> ... </User> <User> <Username>TEST1</Username> ... </User> </UserData> </LoginData>

我需要匹配用户名并删除其他用户标签。

花了我(作为一个完整的 XML 菜鸟)的时间来解决它,但最后我在一个节点上匹配,并删除了父节点的子节点:

对于 oXmlDoc.documentElement.selectSingleNode("UserData").childNodes 中的每个 x 如果 x.getElementsByTagName("Username").item(0).text = "TEST1" 那么 设置 exx = x.getElementsByTagName("用户名").item(0) wscript.echo(x.getElementsByTagName("用户名").item(0).text) wScript.echo(x.nodename & ": " & x.text) x.parentNode.removeChild(x) 万一 下一个

【讨论】:

以上是关于如何使用 vbscript 删除 XML 文件中的特定节点的主要内容,如果未能解决你的问题,请参考以下文章

如何在不实际提取文件的情况下使用 VBScript 读取 .zip 文件的内容?

如何使用 JAVA 删除 XML 中的节点

如何在vbscript中的文件中间写文本? [关闭]

如何在骆驼XML路径中删除一部分文件名

使用 Linq 删除 XML 中的子节点

VB.NET:使用 XDocument 在 XML 文件中添加/编辑/删除 XElement