如何使用 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 文件中的特定节点的主要内容,如果未能解决你的问题,请参考以下文章