1

我试图通过克隆各种节点(和节点组)来使用 Python 从 XML 文件中读取数据结构,然后更改节点中的一些数据并将其粘贴到新的 .xml 文件中。

我目前有这个代码 - 它包含在一个 for 循环中,因为我试图从一个克隆节点创建多个节点。每个新节点与克隆的数据略有不同:

i = 1

for alias in newchannels[:]:

    #split'alias' at commas and assign to content - this bit is just to retrieve the    correct data to be pasted into the nodes later
    content = alias.split(',')
    #extract data from array
    channelname = content[0]
    #ditto
    ip = content[2]
    port = content[3]

    #get channel info
    root_sChannel = root_sChannelList.getElementsByTagName("servermain:Channel")[0]
    #blank channel node
    root_sChannelClone = root_sChannel.cloneNode(False)

    #root_sChannelClone.firstChild.data = "SimulationChannel " + str(i)

    #clone servermain:Name attribute from previous xml file

    servermainName = root_sChannel.getElementsByTagName("servermain:Name")[0]

    #clone it
    servermainNameClone = servermainName.cloneNode(True)

    servermainNameClone.data = "SimulationChannel" + str(i)
    #this bit prints the data fine 
    print servermainNameClone.data
    #servermainNameClone.setAttributeNode("Simulation Channel" + str(i)) 

    #append to channel clone
    root_sChannelClone.appendChild(servermainNameClone)
    #this bit still prints the data fine
    print servermainNameClone.data

    #append other data here

    root_sChannelListClone.appendChild(root_sChannelClone)

    i+=1

我遇到的问题是,虽然在最后附加节点之前数据似乎设置得很好(由打印语句检查),但当我实际检查输出文件时,它实际上只是获取了“更深”的数据'.cloneNode(True)' 节点并直接复制它而不做任何更改,这对我来说绝对没有意义。我使用了错误的数据更改功能还是什么?

编辑:请找到完整的代码:

    #include necessary modules
import xml.dom.minidom
import csv
import os
import argparse
import sys

#set defaults
WELLS_FILE = "wells.csv"
CONFIG_FILE = "OPCServerConfig.xml"
UPDATE_FILE = "UpdatedConfig.xml"

#set constants for the column locations in CSV file
_Tenement=0
_Well=1
_Type=2
_Descr=3
_RealIP=4
_TestIP=5
_TestPort=6

#set port
_PORT="5020"

global FILES

def parseInput():
    #set up argument parser
    parser = argparse.ArgumentParser(description='Update Kepware Server Configuration with wells information.')
    #add arguments (parameters) to the parser - the info needed when running the program
    parser.add_argument('-wf','--wells', default=WELLS_FILE, help='wells file' )
    parser.add_argument('-cf','--config', default=CONFIG_FILE, help='current configuration file')
    parser.add_argument('-of','--output', default=UPDATE_FILE, help='updated configuration file')

    global FILES
    #above info stored until this line when they are actually used - then creates the necessary objects. sys.arg[1] reads argument 2 onwards from command line
    FILES = parser.parse_args(sys.argv[1:])

    #print out files names
    print FILES.wells
    print FILES.config
    print FILES.output

#reads in well info
def getWellsInfo():
    #set up empty array
    lines = []
    #set header to true by default (i.e. it hasn't found the header yet)
    header = True
    #open the wells.csv file, to be read in binary mode ('rb')
    with open( FILES.wells, 'rb') as wellfile:
            #assign tothe variable reader the wellfile
            reader = csv.reader(wellfile)
            #for each row in the csv file
            for row in reader:
                #if row is empty, or starts with '//' then go to next loop of for statement
                if len(row)==0 or row[0].startswith("//") or not row[0]:
                    continue

                #if header found, set value to false, then go to next loop
                if header:
                    header = False
                    continue

                #assign info from csv file to applicable arrays
                #t_nm = row[ _Tenement ]
                #w_nm = row[ _Well ]
                #real_ip_nm = row[ _RealIP ]
                test_ip_nm = row[ _TestIP ]

                #set up construct for channel name
                #channel = "B%(tnm)03d-w%(wnm)03d" % {'tnm':int(t_nm), 'wnm':int(w_nm) }
                channel = row[ _Descr ]
                # alias = "ARG_WH%(wnm)02d" % {'wnm':int(w_nm) }
                #alias = "B%(tnm)03d-w%(wnm)03d" % {'tnm':int(t_nm), 'wnm':int(w_nm) }
                alias = row[ _Descr ]

                port = row[ _TestPort ]

                #print out info to command prompt
                print channel + ',' + alias + ',' + test_ip_nm.split('/')[0] + ',' + port
                #append info contructs to lines array
                lines.append(channel + ',' + alias + ',' + test_ip_nm.split('/')[0] + ',' + port)

    wellfile.close()
    return lines

def updateCfgFile(newchannels):
    from xml.dom.minidom import parse
    #parse the xml file and assign it to 'doc'
    doc = parse(FILES.config)
    #get the first 'Matrikon.OPC.ScadaModbus' element by tag name and assign it to root
    root = doc.getElementsByTagName("servermain:Project")[0]
    #clone (copy) the node, but not a 'deep' (children) copy, as specified by the 'false' parameter
    rootClone = root.cloneNode(False)

    #get the title element and assign it to the variable root_sTitleClone
    root_sTitle = root.getElementsByTagName("servermain:Title")[0]
    #clone the node but not a deep clone
    root_sTitleClone = root_sTitle.cloneNode(False)

    #as above for comments
    root_sComments = root.getElementsByTagName("servermain:Comments")[0]
    root_sCommentsClone = root_sComments.cloneNode(False)

    #as above for AliasList
    root_sAliasList = root.getElementsByTagName("servermain:AliasList")[0]
    root_sAliasListClone = root_sAliasList.cloneNode(False)

    #as above for GlobalDriverSettingsList, copy all child stuff too (cloneNode:True)
    root_sGDSL = root.getElementsByTagName("servermain:GlobalDriverSettingsList")[0]
    root_sGDSLClone = root_sGDSL.cloneNode(True)


    #append the children to the rootClone hierarchy
    rootClone.appendChild( root_sTitleClone )
    rootClone.appendChild( root_sCommentsClone )
    rootClone.appendChild( root_sAliasListClone )
    rootClone.appendChild( root_sGDSLClone )

    #as above for ChannelList
    root_sChannelList = root.getElementsByTagName("servermain:ChannelList")[0]
    root_sChannelListClone = root_sChannelList.cloneNode(False)







    #for loop interation
    i=1
    #create array 'newchannels' and cycle through it using indexes 'alias'
    for alias in newchannels[:]:
        #split'alias' at commas and assign to content
        content = alias.split(',')
        #extract data from array
        channelname = content[0]
        #ditto
        ip = content[2]
        port = content[3]

        #get channel info
        root_sChannel = root_sChannelList.getElementsByTagName("servermain:Channel")[0]
        #blank channel node
        root_sChannelClone = root_sChannel.cloneNode(False)

        #root_sChannelClone.firstChild.data = "SimulationChannel " + str(i)

        #clone servermain:Name attribute from previous xml file
        servermainName = root_sChannel.getElementsByTagName("servermain:Name")[0]
        #clone it
        servermainNameClone = servermainName.cloneNode(True)

        servermainNameClone.data = "SimulationChannel" + str(i) 
        print servermainNameClone.data
        #servermainNameClone.setAttributeNode("Simulation Channel" + str(i)) 

        #append to channel clone
        root_sChannelClone.appendChild(servermainNameClone)
        print servermainNameClone.data

        #append other data here

        root_sChannelListClone.appendChild(root_sChannelClone)

        i+=1


        #sDriver = root_sChannel.getElementsByTagName("servermain:Driver")
        #root_sChannelClone.appendChild(sDriver)




        #set name of channel clone
        #root_sChannelClone_ServerName.setAttribute("servermain:Name", "Simulation Channel " + str(i))

        #root_sChannelCloneDeviceList = root_sChannel.getElementsByTagName("servermain:DeviceList")

        #root_sChannelCloneDevice = root_sChannelCloneDeviceList.getElementsByTagName("servermain:Device")[0]

        #root_sChannelCloneDevice.setAttribute("servermain:Name", channelname)
        #root_sChannelCloneDeviceList.setAttribute("servermain:Name", "value inserted here")

        #root_sChannelCloneDevice.setAttribute("servermain:ID", ip)
        #root_sChannelCloneDeviceList.setAttribute("servermain:ID", "IP Inserted here")

        #root_sChannelCloneDevice.setAttribute("Modbus_ethernet:Port", port)
        #root_sChannelCloneDeviceList.setAttribute("Modbus_ethernet:Port", "portnumber here")

        #root_sChannelListClone.appendChild ( root_sChannelClone )


    rootClone.appendChild( root_sChannelListClone )

    #rootClone.appendChild( root_sChannelListClone )
    '''    
    #print out channel name, ip and port
    for channel in rootDevLinkClone.getElementsByTagName("CNetworkChannelDevLink"):
        name = channel.getAttribute("name")
        devlink = channel.getElementsByTagName("CHostDevLink")[0]
        ip = devlink.getAttribute("host")
        port = devlink.getAttribute("service")
        print name + ' ' + ip + ' ' + port
    '''
    #PSTAliasGroup = rootAlias.getElementsByTagName("PSTAliasGroup")[0]

    #for alias in newchannels[:]:
    #    channelname = alias.split(',')[0]
    #    aliasname = alias.split(',')[1]
    #    GroupClone = PSTAliasGroup.cloneNode(True)
    #    GroupClone.setAttribute("name",aliasname)
    #    Taglist = GroupClone.getElementsByTagName("PSTAlias")
    #    for tag in Taglist[:]:
    #        pathlist = tag.getAttribute("itemPath").split('.')
    #        newpath = channelname
    #        for pathfrag in pathlist[1:]:
    #            newpath += '.' + pathfrag
    #        tag.setAttribute("itemPath", newpath)
    #    rootAliasClone.appendChild(GroupClone)

    print "Saving..."

    ## This makes a second, larger copy of the XML data !!
    # xmlString = rootClone.toprettyxml()

    #output the file
    outputfile = open(FILES.output, 'w')
    #outputfile.write(xmlString)

    #write xml of the root clone hierarchy
    rootClone.toprettyxml(indent='  ')
    rootClone.writexml(outputfile, "    ", "    ", "\n");
    outputfile.close()
#print xmlString

#call the parse input function - sets up user argument validating etc       
parseInput()

print FILES

#call the get wells info function - retrieves all necessary info from the wells.csv file
ips = getWellsInfo()

print ips

#call update cfg file
updateCfgFile(ips)
4

0 回答 0