替换For-Each中的XML值并返回函数

时间:2016-06-17 04:17:10

标签: vbscript xml-parsing xmldom

我在这里的脚本试图通过XML文件进行递归,将每个RegEx匹配(存储在搜索数组中)存储到2个结果数组中; 1表示开始日期,1表示结束日期。 检查两个数组的Ubounds是否相等然后将文本传递给使用XMLDOM在每个父节点中查找End_Date节点的函数,然后将该文本传递给另一个函数,添加30天然后将其传回,替换之前的值。然后它应该将内容写回文件并保存。

我在这里遇到了一些问题。 1.我无法将+30天的值传递回第一个父节点之后的任何内容 - 内存空间似乎保留了之前For-Each迭代的+30天值。我无法将任何内容写回文件。

我最初是为文本文件编写的,但随着我们项目的要求发生变化,格式已更改为XML。

我希望能够在vbscript的XMLDOM中完成所有操作,并且只需使用函数来进行特定的数据更改。但我主要担心的是我的草率脚本没有做基础知识。

任何人都可以通过指出我正在运行的循环中的缺陷来帮助我吗?我已经撞墙了,似乎无法取得更多进展!

这是我正在阅读的XML文件(缩短为2个广告节点,已删除大量子节点):

<?xml version="1.0" encoding="utf-8"?>
<XMLFeederRoot>
<ADS_CREATE_TIME>2016-06-07T01:35:39</ADS_CREATE_TIME>
<Ad>
  <Ad_Number>d00524224</Ad_Number>
  <Start_Date>2016-08-20T00:00:00</Start_Date>
  <End_Date>2016-08-20T00:00:00</End_Date>
  <Status>Run</Status>
</Ad><Ad>
  <Ad_Number>d00524225</Ad_Number>
  <Start_Date>2016-08-20T00:00:00</Start_Date>
  <End_Date>2016-08-20T00:00:00</End_Date>
  <Status>Run</Status>
</Ad>
</XMLFeederRoot>

这是脚本:

'Setting the Regular Expression object and setting occurrences to all in strings searched.
Set objRegEx= CreateObject("VBScript.RegExp")
objRegEx.Global= True

set Shell= createobject("wscript.shell")
Dim FSO, FLD, FIL, TS, strDate, strEDat, i, d, c
Dim strFolder, strContent, strPath
Const ForReading= 1, ForWriting= 2 

strFolder= "C:\Scripts\Run"

Set FSO= CreateObject("Scripting.FileSystemObject")

'Get a reference to the folder you want to search
set FLD= FSO.GetFolder(strFolder)

'loop through the folder and get the files
For Each Fil In FLD.Files

'Open the file to read
Set TS= FSO.OpenTextFile(fil.Path, ForReading)

'Read the contents into a variable
strContent= TS.ReadAll

'Close the file
TS.Close


reDim arrMR(1,1)
    arrMR(0,0)= "(\s+)(<Start_Date>(.*?)<\/Start_Date>)"
    arrMR(1,0)= "(\s+)(<End_Date>(.*?)<\/End_Date>)"


For i= 0 to Ubound(arrMR)
    objRegEx.Pattern= arrMR(i,0)
    Set objMatches= objRegEx.Execute(strContent)


d=0

    For Each objMatch in objMatches
        If i= 0 Then
            If d>0 Then
                reDim Preserve arrStart(d)
            Else
                reDim arrStart(d)
            End If
                arrStart(d)= objMatches.Item(d).SubMatches(2)

                'Wscript.Echo arrStart(d)
        ElseIf i<> 0 Then
            If d>0 Then
                reDim Preserve arrEnd(d)
                ReDim Preserve arrMatch1(d)
            Else
                reDim arrEnd(d)
                ReDim arrMatch1(d)
            End If
                arrEnd(d)= objMatches.Item(d).SubMatches(2)         
                arrMatch1(d)= objMatches.Item(d).SubMatches(1)

        End If



        If objRegEx.Pattern<> arrMR(0,0) Then
            If (ubound(arrStart)= ubound(arrEnd)) Then
                'Wscript.Echo "Ubounds Match"   
                            Parse strContent
                            strContent= Parse(strContent)
            Else
                'Wscript.Echo "Start & End Dates do not match"
            End If
        End If          
            d= d+ 1 'increment to next match

    Next

Next    

'Close the file
TS.Close

'Open the file to overwrite the contents
Set TS= FSO.OpenTextFile(fil.Path, ForWriting)

'Write the contents back
TS.Write strContent

'Close the current file
TS.Close

Next

'Clean up
Set TS= Nothing
Set FLD= Nothing
Set FSO= Nothing


Function Parse(ParseContent)

  'Dim sFSpec : sFSpec   =   FSO.GetAbsolutePathName("C:\Users\j.levine\Desktop\XML Feeder                 Scripts\Test_Files\monvid.txt")
  Dim oXML   : Set oXML = CreateObject("Msxml2.DOMDocument.6.0")  
  Dim strXMLSDat, strXMLarrStartD, XMLEDat
  oXML.setProperty "SelectionLanguage", "XPath"
  oXML.async = False
  oXML.loadXML(ParseContent)

  If 0 = oXML.parseError Then
     Dim sXPath3 : sXPath3    = "//XMLFeederRoot/Ad[End_Date=Start_Date]"
     Dim ndlFnd : Set ndlFnd = oXML.selectNodes(sXPath3)
     If 0 = ndlFnd.length Then
        WScript.Echo sXPath, "not found"
     ElseIf 0<> ndlFnd.length Then       
        'WScript.Echo "found", ndlFnd.length, "nodes for", sXPath
        Dim ndCur, oldNode
        For Each ndCur In ndlFnd    
            oldNode = oXML.selectsinglenode("//End_Date").text
            oldNode= XMLSplitArray(oldNode) 'Pass current Date into Array and add 30 days & return as node text
            Set newNode= oXML.selectSingleNode("//End_Date")
            newNode.text= oldNode
            WScript.Echo ndCur.xml

        Next
        'WScript.Echo "We have nothing to replace"
     End If
  Else
     WScript.Echo oXML.parseError.reason
  End If

  Parse= ParseContent
End Function


Function XMLSplitArray(strval1)

dim XmlSA, XmlSA2, XMLEDat

XmlSA = split(strval1, "-")
XmlSA(2) = Left(XmlSA(2), 2)
strXMLDate = XmlSA(1) & "/" & XmlSA(2) & "/" & XmlSA(0)
strXMLDate30 = DateAdd("d", 30, strXMLDate)

XmlSA2 = split(strXMLDate30, "/")

'Add zero to the left
XmlSA2(0)= Right("0" & XmlSA2(0), 2)
XmlSA2(1)= Right("0" & XmlSA2(1), 2)

XmlSA2(1) = XmlSA2(1) & "T00:00:00"
XMLEDat = XmlSA2(2) & "-" & XmlSA2(0) & "-" & XmlSA2(1)
XMLSplitArray= XMLEDat

End Function

2 个答案:

答案 0 :(得分:0)

由于Text和XML文件默认情况下不使用文件锁,只需使用xmlDoc.Save monvidPath覆盖原始文件。

private static bool IsBOMWhitespace(char c)
{
     #if FEATURE_LEGACYNETCF
     if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8 && c == '\xFEFF')
     {
         // Dev11 450846 quirk:
         // NetCF treats the BOM as a whitespace character when performing trim operations.
         return true;
     }
     else
     #endif
     {
         return false;
     }
}

答案 1 :(得分:0)

托马斯对KISS方法是正确的。我退了一大步,重新开始。

这是我提出的问题。它做了我需要的关于Date + 30并写回文件。我认为这种方法更清晰,并且允许我通过函数运行我的其他文本按摩。

我对这个新脚本的疑问是: 1.这可以在不写入新文件的情况下完成吗?保持1个文件更容易。 2.我可以避免克隆节点并删除原始节点并直接更改原始节点的值吗? 3.我似乎不知道如何将最后一个节点<Status>放到它自己的行上。

脚本:

Dim xmlDoc: Set xmlDoc = CreateObject("Msxml2.DOMDocument")
xmlDoc.Async = False
xmlDoc.load "C:\Scripts\Run\MonVid-SHORT.xml"

Dim xmldoc2: set xmldoc2 = CreateObject("Msxml2.DOMDocument")
Dim strSkeleton : strSkeleton= "<?xml version=""1.0"" encoding=""utf-8""?>" & _
                                "<XMLFeederRoot>" & _
                                "</XMLFeederRoot>"
xmldoc2.loadXML(strSkeleton)
xmldoc2.save  "C:\Scripts\Copy\New_MonVid-Short.xml"
xmlDoc2.async = False
xmlDoc2.load "C:\Scripts\Copy\New_MonVid-Short.xml"
Dim sXPath : sXPath     = "/XMLFeederRoot/Ad[Start_Date=End_Date]"


For Each n In XMLDoc.SelectNodes(sXpath)
    set l = n.cloneNode(True)
    q= l.selectSingleNode("/End_Date").text

    strSDat=SplitArray(q)

    l.removeChild(l.childNodes.item(2))
    set Stat= l.selectSingleNode("/Status")
    set Parent= Stat.parentNode
    set EDate= xmlDoc2.createElement("End_Date")
    EDate.appendChild xmlDoc2.createTextNode(strSDat)
    Parent.insertBefore EDate, Stat

    xmldoc2.documentElement.appendChild parent

Next

xmlDoc2.save xmldoc2.url


Function SplitArray(strval1)
dim SplitArray1, SplitArray2, strSDat

splitArray1 = split(strval1, "-")
splitArray1(2) = left(splitArray1(2), 2)
strDate1 = SplitArray1(1) & "/" & SplitArray1(2) & "/" & SplitArray1(0)
strDate30 = DateAdd("d", 30, strDate1)

SplitArray2 = split(strDate30, "/")

'Add zero to the left
If Len(SplitArray2(0))<2 Then 
    SplitArray2(0)= Right("0" & SplitArray2(0), 2)
End If
If Len(SplitArray2(1))<2 Then 
    SplitArray2(1)= Right("0" & SplitArray2(1), 2)
End If

SplitArray2(1) = splitArray2(1) & "T00:00:00"
strSDat = SplitArray2(2) & "-" & SplitArray2(0) & "-" & SplitArray2(1)
SplitArray= strSDat

End Function

输出文件:

<?xml version="1.0" encoding="utf-8"?>
<XMLFeederRoot><Ad>
        <Ad_Number>d00524224</Ad_Number>
        <Start_Date>2016-08-20T00:00:00</Start_Date>
        <End_Date>2016-09-19T00:00:00</End_Date><Status>Run</Status>
    </Ad><Ad>
        <Ad_Number>d00524225</Ad_Number>
        <Start_Date>2016-08-20T00:00:00</Start_Date>
        <End_Date>2016-09-19T00:00:00</End_Date><Status>Run</Status>
    </Ad>
</XMLFeederRoot>