XML Parsing

francois
2012-05-16
2012-10-25
  • francois - 2012-05-16

    Hello,

    I am trying to create a script where I can build different versions of my applications by toggling pragma variables declaration.
    I understand that the only way to change the code at this point would be:
    1. Export the gvl as XML
    2. Modify the XML
    3. Import back the modified XML

    My problem is: how can I modify the XML? Ironpython has no implementation of pyexpat.py, so nothing like dom, minodom or etree will work. I could use some .net constructs, but trying to import CLR gives me an error "Access to module clr not permitted".

    Why restrict access to CLR......?

     
  • Anonymous - 2012-05-16

    Originally created by: M.Schaber

    Hi, Francois,

    francois hat geschrieben:
    I am trying to create a script where I can build different versions of my applications by toggling pragma variables declaration.
    I understand that the only way to change the code at this point would be:
    1. Export the gvl as XML
    2. Modify the XML
    3. Import back the modified XML
    My problem is: how can I modify the XML? Ironpython has no implementation of pyexpat.py, so nothing like dom, minodom or etree will work.

    As soon as IronPython has a working XML implementation, we intend to ship it with CoDeSys. So the "best" way is to contribute a working XML implementation to the IronPython project. This gives a lot of positive karma.

    francois hat geschrieben:
    I could use some .net constructs, but trying to import CLR gives me an error "Access to module clr not permitted".

    Since V3.5, the System.Xml assembly is available for IronPython scripts:

    import System
    doc = System.Xml.XmlDocument()
    

    For older CoDeSys versions, the possible workarounds include:
    [list=]
    [*]You can execute external commands (including cPython scripts) to process the XML for you.
    [*]Use Pyro or some other remote call tools to call a cPython "server" processing your requests
    [*]Use the ctypes module to import some native library which does the processing.
    [*]Modify the XML using simple text manipulation (this works for some simple cases.)
    [/list]

    francois hat geschrieben:
    Why restrict access to CLR......?

    For several (mostly political) reasons, the ScriptEngine is "sandboxed" a little bit. If there are convincing usecases for access to the clr module, we might remove or rework that restriction, or expose the required functionality in a different way. Note that Automation Platform plugins are free to lift this restriction when they instantiate Script Executors for their own purposes.

     
  • francois - 2012-05-17

    Thanks for your answer!

    With the System.Xml assemblies, it means minidom can be used with the following manipulations:

    1.Take the CPython expatbuilder.py and copy it to the xml/dom scripts folder
    2. With a slight modification to FePy's pyexpat.py , rename it to expat.py and copy it to xml/parsers scripts folder

    \#import clr
    \#clr.AddReference("System.Xml")
    

    This enables the standard python xml implmentations!

    Regards,
    Francois

     
  • Anonymous - 2012-05-18

    Originally created by: M.Schaber

    Hi, Francois,

    francois hat geschrieben:
    With the System.Xml assemblies, it means minidom can be used with the following manipulations:
    1.Take the CPython expatbuilder.py and copy it to the xml/dom scripts folder
    2. With a slight modification to FePy's pyexpat.py , rename it to expat.py and copy it to xml/parsers scripts folder

    \#import clr
    \#clr.AddReference("System.Xml")
    

    This enables the standard python xml implementations!

    This is great news, thanks!

    I just tested it, and it seems to work. I'll try to get this into V3.5 SP2. (It is to late for 3.5 SP1, code close was more than 1 month ago...)

    The last time when I checked pyexpat.py, it did not really work well - even using minidom did not work. (And I tested it in plain IronPython without CoDeSys.)

     
  • Anonymous - 2012-07-02

    Originally created by: M.Schaber

    Hi,

    Just another update: In our Jira-Database, we opened issue CDS-29369 to rework the sandboxing so "import clr" is allowed.

    If you need "import clr" functionality, it is best to use your official support contact to get your company added to this jira entry.

    HTH,
    Markus

     
  • Anonymous - 2012-10-24

    Originally created by: M.Schaber

    Hi,

    Good news: the change which allows "import clr" did just slip into V3.5 SP2 (which is scheduled for december).

    There are some filters in the AddReferenceXXX()-Calls which prohibit access to CODESYS internal APIs, but all other .NET Assemblies are freely accessible.

    HTH,
    Markus

     
  • daniel-REC - 2012-10-25

    Hi,

    As a solution to this I will show You script that I did create and it is used to module parameter changing. Basically it export module info to xml file, modify line with parameters and import this file again.

    from __future__ import print_function
    from ConfigParser import SafeConfigParser
    import os, ctypes, sys
    PATH = r"C:\\TestStand\\Systemtest\\Libs\\CoDeSys\\"
    BUS == 'Profinet'
    COUPLER = 'Profinet_Coupler_Name'
    MODULE = 'Analog_Module_Name'
    IN_FILE = PATH + "export.xml"
    OUT_FILE = PATH + "import.xml"
    TCMASTER = PATH + "tcMaster.txt"
    Line = 1
    \# create the export reporter
    class Reporter(ExportReporter):
       def error(self, message):
          system.write_message(Severity.Error, message)
       def warning(self, message):
          system.write_message(Severity.Warning, message)
       def resolve_conflict(self, obj):
          return ConflictResolve.Copy
       def nonexportable(self):
          print("non exportable")
       @property
       def aborting(self):
          return False
    \# create the exporter instance.
    exp_reporter = Reporter()
          
    \# create the import reporter
    class Reporter(ImportReporter):
       def error(self, message):
          system.write_message(Severity.Error, message)
       def warning(self, message):
          system.write_message(Severity.Warning, message)
       def resolve_conflict(self, obj):
          return ConflictResolve.Copy
       def added(self, obj):
          print("added: ", obj)
       def replaced(self, obj):
          print("replaced: ", obj)
       def skipped(self, obj):
          print("skipped: ", obj)
       @property
       def aborting(self):
          return False
    \# create the importer instance.
    imp_reporter = Reporter()
    def subStrXml():
       lRetVal=0
       if BUS == 'Profinet':
          PRETAG = '<Element name="RecordData">'
          POSTTAG = '</Element>'
       else: #'Profibus'
          PRETAG = '<Element name="userParameter">'
          POSTTAG = '</Element>'
       IN_BLOCK = False
       pos1 = -42
       pos2 = -42
       OUT = "";
       fhIn = open(IN_FILE,"r")
       fhOut = open(OUT_FILE,"w")
       TCM = SafeConfigParser()
       TCM.read(TCMASTER)
       print('Build: Text: Modifying file...')
       # replace module parameters in xml file
       for line in fhIn:   
          pos1 = line.find(PRETAG) # look for begin
          pos2Offset = 0
          if pos1 >= 0 :
             pos2Offset = pos1
             pos2 = line.find(POSTTAG, pos2Offset) # look for end, maybe same line
          if pos1 > 0 :
             IN_BLOCK = True
             OUT += line[0:pos1+len(PRETAG)]
             try:
                OUT += TCM.get('DEFAULT', "Line"+INDEX).split(';')[int(SUBIDX)]
             except:
                print('Error: tcMaster - TC not found or index out of bound')
                lRetVal=1
                
          if pos2 > 0 and IN_BLOCK == True :
             IN_BLOCK = False
             OUT += line[pos2:]
          if ( pos1 < 0 or pos2 < 0 ) and not IN_BLOCK:
             OUT += line
          pos1 = -42
          pos2 = -42
       fhOut.write(OUT)
       fhIn.close()
       fhOut.close()
       return lRetVal
    if BUS == 'Profibus':
       project = PATH + "Projekt\SysTS_FBC-PB-DP\\SysTS_FBC-PB-DP.project"
       COUPLER = 'UR20_FBC_PB_DP'
    elif BUS == 'Profinet':
       project = PATH + "Projekt\SysTS_FBC-PN\\SysTS_FBC-PN.project"
       COUPLER = 'UR20_FBC_PN_IRT_Profinet_Device'
    else:
       print('Build: Error: Bus ' + BUS + ' not found')
       flag = 9
       globData.write(globData.compile())
       system.delay(3000)
       system.exit()
    print('Build: Text: UUT Connection Type: ' + BUS)
    \# main program
    \# export module to xml
    obj = proj.find(MODULE, True)
             
    if (len(obj) > 0):
       obj[0].export_xml(exp_reporter, IN_FILE, True)
                
       # change module parameters
       returnValue = subStrXml()
             
       if (returnValue != 0):
          print('Error')
             
       else:
          dev = proj.find(COUPLER, True)
                
          # import module, move to correct position and run application
          module_index = obj[0].index
          obj[0].remove()
          dev[0].import_xml(imp_reporter, OUT_FILE)
          obj = proj.find(MODULE, True)
          obj[0].move(dev[0], module_index)
          os.remove(OUT_FILE)
                   
    else:
       print('Build: Error: Object not found')
    

    And the tcMaster file kooks like this:

    [DEFAULT]
    Line1=[16#0A,16#00,16#04,16#01,16#0F,16#00,16#09,16#09,16#09,16#09]
    Line2=[16#0A,16#00,16#04,16#01,16#0F,16#00,16#0A,16#0A,16#0A,16#0A]

    It is easy to modify this to Your needs.

     

Log in to post a comment.