замена значений XML в For-Each и возврат в функцию

Сценарий, который у меня есть, пытается выполнить рекурсию через файл XML, сохраняя каждое совпадение RegEx (хранящееся в массиве поиска) в 2 массива результатов; 1 для даты начала, 1 для даты окончания. Границы обоих массивов проверяются на равенство, затем текст передается функции, которая использует XMLDOM для поиска узла End_Date в каждом родительском узле, затем передает этот текст другой функции, добавляя 30 дней, а затем возвращая его обратно, заменяя предыдущее значение. . Затем предполагается записать содержимое в файл и сохранить его.

У меня тут несколько проблем. 1. Я не могу получить значение +30 дней, которое будет передано чему-либо за пределами первого родительского узла - пространство памяти, похоже, сохраняет значение +30 дней из предыдущей итерации For-Each. 2. Я не могу ничего записать обратно в файл.

Сначала я писал для текстовых файлов, но формат изменился на XML, так как требования к нашему проекту изменились.

Я хотел бы иметь возможность делать все это в XMLDOM в vbscript и просто использовать функции для внесения конкретных изменений данных. Но больше всего меня беспокоит мой небрежный сценарий, не выполняющий основ.

Может ли кто-нибудь помочь мне, указав на недостатки в циклах, которые я запускаю? Я врезался в стену и просто не могу добиться большего прогресса!

Вот 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

person Jason Levine    schedule 17.06.2016    source источник


Ответы (2)


Томас был прав с методом KISS. Я сделал большой шаг назад и начал сначала.

Вот что я придумал. Он делает то, что мне нужно в отношении даты + 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>
person Jason Levine    schedule 19.06.2016

Поскольку текстовые и XML-файлы по умолчанию не используют блокировки файлов, просто перезапишите исходный файл с помощью xmlDoc.Save monvidPath.

Sub setAdEndDate(monvidPath)
    Const sXPath  = "/XMLFeederRoot/Ad/End_Date"

    Set xmlDoc = CreateObject("Microsoft.XMLDOM")

    xmlDoc.Async = "False"
    xmlDoc.Load(monvidPath)

    Set colNodes=xmlDoc.selectNodes(sXPath)

    For Each n In colNodes

        n.Text = SplitArray(n.Text)

    Next

    xmlDoc.Save monvidPath

End Sub

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
person Community    schedule 17.06.2016
comment
В простейшем случае да, это было бы проще, и я сделал это в других частях этого скрипта, которые я удалил, так как они не были проблемными местами. Я думаю, что сделал это слишком сложным из-за множества изменений, которые мне бросают, и я пытаюсь совместить множество разных способов сделать что-то вместе. - person Jason Levine; 19.06.2016