代码之家  ›  专栏  ›  技术社区  ›  Marcus

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

  •  0
  • Marcus  · 技术社区  · 16 年前

    我遇到的问题是无法选择需要删除的特定XML节点。我已经尝试使用xpath来选择节点,这对一些XML文件很有用,但是我无法在更复杂的文件中找出节点的正确xpath。

    有人知道一个免费软件工具可以加载一个XML文件,这样用户就可以选择一个特定的节点并接收准确的xpath,而不需要在路径中进行枚举吗?

    /root/anything[2] <--不幸的是,我不能使用这样的语句,因为元素的数目可能会改变。我需要一个基于属性的表达式。

    如果此操作没有免费工具,有人知道如何选择所需节点的其他方法吗?

    XML示例:

    根节点: SMSFATM数据

    属性: 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 对象为空。未选择节点,但为什么?

    8 回复  |  直到 13 年前
        1
  •  2
  •   Luke Bennett    16 年前

    这是默认的命名空间问题。在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 同样有用。

        2
  •  0
  •   Marcus    16 年前

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

    因此,我们来详细讨论一下:

    根节点: SMSFATM数据

    属性: 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对象为空。未选择节点,但为什么?

    哦,顺便说一句:谢谢您的可视xpath提示!我尝试过使用它,但不幸的是它采用了枚举方式:/

        3
  •  0
  •   Xetius    16 年前

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

    objdom.setproperty“selectionlanguage”,“xpath”

    一旦设置了此属性,就可以使用完整的xpath来访问所需的任何元素。

        4
  •  0
  •   Sundar R    16 年前

    如果你有火狐浏览器,你可以简单地安装dom inspector(只有火狐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
  •  0
  •   mdb    16 年前

    给定以下XML:

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

    …您可以使用xpath表达式获取第二个anything节点的值:

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

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

    对于自动生成此类查询的工具,适当命名 Visual XPath 应该这样做,而且是免费的(它甚至附带了C源代码)。

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

    给出上述XML示例,此vbscript:

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

    …返回字符串“value2”:根据您的需要,您可能需要稍微调整一下(同样,还需要一些工具,如VisualXPath或任何好的 XPath reference 会帮你的)。

        6
  •  0
  •   Marcus    16 年前

    嗯…我觉得这个问题必须以文件为基础。 即使我为selectionlanguage设置了属性,并且使用枚举的xpath(通过使用firefox xpather获得),节点对象仍然保持为空。

    有人知道可能出什么问题吗?XML文件随Microsoft应用程序一起提供,因此应该是有效的。至少在打开文件或在应用程序中使用文件时没有任何问题,所以语法应该是正常的。

    或者,是否有人拥有一个vbscript函数,该函数迭代整个XML文件,以查找需要的节点,以便将其删除?

        7
  •  0
  •   AnthonyWJones    16 年前

    您的问题是您有一个默认的名称空间。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""]"
    
        8
  •  0
  •   Stdoubt    16 年前

    不知道这对你有什么用,但我也有类似的问题。

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

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

    我花了很长时间(作为一个完整的XML noob)来解决这个问题,但最后我在一个节点上找到了匹配,并删除了父节点的子节点:

    对于oxmldoc.documentelement.selectsinglenode(“userdata”).childnodes中的每个x 如果x.getElementsByTagname(“用户名”).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)键 结束如果 下一个