在VBScript中删除XML行

时间:2013-12-04 19:13:29

标签: xml vbscript

我在VBScript中获得了以下代码:

Set xmlDoc = CreateObject("Msxml2.DOMDocument.6.0")   
xmlDoc.Async = "False"
xmlDoc.setProperty "SelectionLanguage", "XPath"

For Each f In fso.GetFolder("C:\Users\Admin\Folder").Files
    If LCase(fso.GetExtensionName(f)) = "xml" Then
    xmlDoc.Load f.Path

        If xmlDoc.ParseError = 0 Then

            'Some code in here

        Else
            WScript.Echo "Parsing error! '" & f.Path & "': " & xmlDoc.ParseError.Reason

        End If
    End If
Next

我正在对该目录中的XML文件进行一些操作,但在执行此操作之前,我需要对所有这些XML文件执行一项操作:删除行。类似的东西:

@EDIT(现在NODE1是真正的样本):

    <?xml version="1.0" encoding="UTF-8"?>
    <!-- Created on 2013-11-19T12:00:57+01:00 with ROAMSYS RMS // www.roamsys.com -->
    <tadig-raex-21:TADIGRAEXIR21 xmlns="https://XXX" xmlns:tadig-raex-21="https://XXX" xmlns:tadig-gen="https://YYY" xmlns:xsi="ZZZ" xsi:schemaLocation="https://XXX tadig-raex-ir21-8.2.xsd">
      <NODE2.1>       
        <NODE2.1.1> Information1 </NODE2.1.1> 
        <NODE2.1.2> Information2 </NODE2.1.2> 
        <NODE2.1.3> Information3 </NODE2.1.3>
      </NODE2.1>
      <NODE2.2>
        <NODE2.2.1>XXX</NODE2.2.1>
      </NODE2.2>
   </tadig-raex-21:TADIGRAEXIR21>

转入:

<?xml version="1.0" encoding="UTF-8"?>
      <NODE2.2>
        <NODE 2.2.1> XXX </NODE 2.2.1>
      </NODE2.1>

XML在“xml版本”节点和NODE2.2之间总是有6行。 我打算做的是删除这些行(包括“”)和归档的最后一行,它们总是如此。

我尝试删除节点,因为有些帖子在网站上发布,但如果我不删除这些行,则Xpath不能正常工作。这就是为什么我需要在“行”中思考删除...否则,这是不可能的。 我真的不知道在这些线条中有什么太可怕让我的程序找不到我的路径,但是当我排除它们时,我可以这样做。

我想现在我已经让自己变得更清楚......

有人可以帮帮我吗?

1 个答案:

答案 0 :(得分:3)

如果您要使用以下骨架启动与XML相关的脚本:

  Dim goFS   : Set goFS  = CreateObject("Scripting.FileSystemObject")
  Dim sFSpec : sFSpec    = goFS.GetAbsolutePathName("..\testdata\xml\20383899.xml")
  Dim oXDoc  : Set oXDoc = CreateObject("Msxml2.DOMDocument.6.0")
  oXDoc.async = False
  oXDoc.load sFSpec

  If 0 = oXDoc.ParseError Then
     WScript.Echo "ready to process"
  Else
     WScript.Echo oXDoc.parseError.reason
  End If

您会立即看到您的.XML格式不正确:“NODE 1.2.3”不是名称,NODE2.1节点未关闭,NODE2.2无法关闭/NODE2.1。

所以你的.XML应该是这样的:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created on 2013-11-19T12:00:57+01:00 with ROAMSYS RMS // www.roamsys.com -->
<NODE1>
  <NODE2.1>
    <NODE2.1.1/>
    <NODE2.1.2/>
    <NODE2.1.3/>
  </NODE2.1>
  <NODE2.2>
    <NODE2.2.1> XXX </NODE2.2.1>
  </NODE2.2>
</NODE1>

我确信这样格式良好的.XML可以修改为你想要的结果,但我不明白你的规格:NODE1应该被'删除'/ XML减少到NODE2.2吗?

添加吃我的布丁:

有点作弊,但如果这个代码片段插入骨架中:

  If 0 = oXDoc.ParseError Then
     WScript.Echo "ready to process"
     Dim sXPath : sXPath    = "/NODE1/NODE2.2"
     Dim ndFnd  : Set ndFnd = oXDoc.SelectSingleNode(sXPath)
     If ndFnd Is Nothing Then
        WScript.Echo sXpath, "not found"
     Else
        Set oXDoc.documentElement = ndFnd
        WScript.Echo oXDoc.xml
     End If
  Else

结果:

<?xml version="1.0"?>
<!-- Created on 2013-11-19T12:00:57+01:00 with ROAMSYS RMS // www.roamsys.com -->
<NODE2.2>
        <NODE2.2.1> XXX </NODE2.2.1>
</NODE2.2>

确认您的规格(一种解释)。 如果你不能强迫XML的作者遵守标准,你应该使用text / string ops(RegExp,Replace,...)预先处理坏的XML,然后然后进行转换。通常的方式。 (我承认不知道如何使用RegExp纠正用于关闭错误的任意'错误标签)

更新我:

为了显示策略的可行性“将垃圾转换为有效的XML并处理它”,我写了这个特殊的脚本:

Option Explicit

Dim goFS   : Set goFS  = CreateObject("Scripting.FileSystemObject")
Dim sFSpec : sFSpec    = goFS.GetAbsolutePathName("..\testdata\xml\20383899.org.xml")
Dim sAll   : sAll      = goFS.OpenTextFile(sFSpec).ReadAll()
WScript.Echo "-------------------- garbage in"
WScript.Echo sAll

Dim reZapBlanks : Set reZapBlanks = New RegExp
reZapBlanks.Global     = True
reZapBlanks.Pattern    = "(NODE)(\s+)(\d)"
sAll = reZapBlanks.Replace(sAll, "$1$3")
Dim reAddClose : Set reAddClose = New RegExp
reAddClose.Global     = True
reAddClose.Pattern    = "(<NODE2\.1\.\d+)(>)"
sAll = reAddClose.Replace(sAll, "$1/$2")
Dim reVoodoo : Set reVoodoo = New RegExp
reVoodoo.Global     = False
reVoodoo.Pattern    = "(</NODE2\.1>[\s\S]+)(</NODE2\.1>)"
sAll = reVoodoo.Replace(sAll, "$1</NODE2.2>")
WScript.Echo "-------------------- nice XML out"
WScript.Echo sAll

Dim oXDoc  : Set oXDoc = CreateObject("Msxml2.DOMDocument.6.0")
oXDoc.setProperty "SelectionLanguage", "XPath"
oXDoc.async = False
oXDoc.loadxml sAll ' <-- clean XML

If 0 = oXDoc.ParseError Then
   WScript.Echo "ready to process"
   Dim sXPath : sXPath    = "/NODE1/NODE2.2"
   Dim ndFnd  : Set ndFnd = oXDoc.SelectSingleNode(sXPath)
   If ndFnd Is Nothing Then
      WScript.Echo sXpath, "not found"
   Else
      Set oXDoc.documentElement = ndFnd
      WScript.Echo "-------------------- condensed using std XML methods"
      sAll = oXDoc.xml
      WScript.Echo sAll
      oXDoc.loadxml sAll ' <-- condensed XML
      WScript.Echo "-------------------- sanity check"
      WScript.Echo "Error:", oXDoc.ParseError.errorCode
   End If
Else
   WScript.Echo oXDoc.parseError.reason
End If

输出:

cscript 20383899.vbs
-------------------- garbage in
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created on 2013-11-19T12:00:57+01:00 with ROAMSYS RMS // www.roamsys.com -->
<NODE1>
  <NODE2.1>
    <NODE 2.1.1>
    <NODE 2.1.2>
    <NODE 2.1.3>
  </NODE2.1>
  <NODE2.2>
    <NODE 2.2.1> XXX </NODE 2.2.1>
  </NODE2.1>
</NODE1>

-------------------- nice XML out
<?xml version="1.0" encoding="UTF-8"?>
<!-- Created on 2013-11-19T12:00:57+01:00 with ROAMSYS RMS // www.roamsys.com -->
<NODE1>
  <NODE2.1>
    <NODE2.1.1/>
    <NODE2.1.2/>
    <NODE2.1.3/>
  </NODE2.1>
  <NODE2.2>
    <NODE2.2.1> XXX </NODE2.2.1>
  </NODE2.2>
</NODE1>

ready to process
-------------------- condensed using std XML methods
<?xml version="1.0"?>
<!-- Created on 2013-11-19T12:00:57+01:00 with ROAMSYS RMS // www.roamsys.com -->
<NODE2.2>
        <NODE2.2.1> XXX </NODE2.2.1>
</NODE2.2>

-------------------- sanity check
Error: 0

RegExps适合这种特定的垃圾;我并不认为可以以类似的方式清理下一个错误的XML。

更新II:

@ Charlie的XML输入的最后一个版本是格式良好的。因此可以使用XML方法处理它(XPATH以查找NODE2.2节点并分配到.documentElement以将.XML文件缩减/压缩到该节点)。因此,不需要以上所有的琐事。

我希望这个问题的历史将让每个人都三思而后行,当“从XML中删除行”的粗俗概念引起其丑陋的脑袋时。