0

我遇到的问题是我无法选择需要删除的特定 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 文件名" 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对象是空的。节点没有被选中,但是为什么呢?

4

8 回答 8

2

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

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

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

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也很有用。

于 2008-10-06T11:17:34.993 回答
0

给定以下 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 参考都可以帮助您)。

于 2008-10-06T09:59:35.307 回答
0

感谢您的快速回复!这肯定适用于简单的情况,但这不适用于我的具体情况:(

因此,让我们进入细节:

根节点: 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 文件名" 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 提示!我尝试过使用它,但不幸的是它采用了枚举方式:/

于 2008-10-06T10:27:58.137 回答
0

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

objDOM.SetProperty "SelectionLanguage", "XPath"

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

于 2008-10-06T10:32:19.813 回答
0

如果您有 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 似乎尽可能使用属性(而不是枚举)来识别节点(至少这是我在我的小实验中发现的......)。希望有帮助...

于 2008-10-06T10:33:21.730 回答
0

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

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

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

于 2008-10-06T11:09:14.107 回答
0

你的问题是你有一个默认的命名空间。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""]"
于 2008-10-06T11:17:04.170 回答
0

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

我有一个需要管理的应用程序生成的 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("Username").item (0) wscript.echo(x.getElementsByTagName("Username").item(0).text) wScript.echo(x.nodename & ": " & x.text) x.parentNode.removeChild(x) end if next

于 2009-01-19T22:35:20.367 回答