--- a/plcopen/plcopen.py Tue Sep 03 23:39:22 2013 +0200
+++ b/plcopen/plcopen.py Thu Sep 05 10:36:33 2013 +0200
@@ -124,6 +124,7 @@
return test_result
PLCOpenParser = GenerateParserFromXSD(os.path.join(os.path.split(__file__)[0], "tc6_xml_v201.xsd"))
+PLCOpen_XPath = lambda xpath: etree.XPath(xpath, namespaces=PLCOpenParser.NSMAP)
LOAD_POU_PROJECT_TEMPLATE = """
<project xmlns:ns1="http://www.plcopen.org/xml/tc6_0201"
@@ -170,21 +171,22 @@
return etree.fromstring(project_xml, PLCOpenParser)
+project_pou_xpath = PLCOpen_XPath("/ppx:project/ppx:types/ppx:pous/ppx:pou")
def LoadPou(xml_string):
root = etree.fromstring(
LOAD_POU_PROJECT_TEMPLATE % xml_string,
PLCOpenParser)
- return root.xpath(
- "/ppx:project/ppx:types/ppx:pous/ppx:pou",
- namespaces=PLCOpenParser.NSMAP)[0]
-
+ return project_pou_xpath(root)[0]
+
+project_pou_instances_xpath = {
+ body_type: PLCOpen_XPath(
+ "/ppx:project/ppx:types/ppx:pous/ppx:pou[@name='paste_pou']/ppx:body/ppx:%s/*" % body_type)
+ for body_type in ["FBD", "LD", "SFC"]}
def LoadPouInstances(xml_string, body_type):
root = etree.fromstring(
LOAD_POU_INSTANCES_PROJECT_TEMPLATE(body_type) % xml_string,
PLCOpenParser)
- return root.xpath(
- "/ppx:project/ppx:types/ppx:pous/ppx:pou[@name='paste_pou']/ppx:body/ppx:%s/*" % body_type,
- namespaces=PLCOpenParser.NSMAP)
+ return project_pou_instances_xpath[body_type](root)
def SaveProject(project, filepath):
project_file = open(filepath, 'w')
@@ -303,27 +305,26 @@
setattr(contentheader_obj, attr, value)
setattr(cls, "setcontentHeader", setcontentHeader)
- def gettypeElement(self, element_type, name):
- elements = self.xpath(
- "ppx:types/ppx:%(element_type)ss/ppx:%(element_type)s[@name='%(name)s']" % locals(),
- namespaces=PLCOpenParser.NSMAP)
- if name is None:
- return elements
- elif len(elements) == 1:
- return elements[0]
- return None
- setattr(cls, "gettypeElement", gettypeElement)
-
+ def gettypeElementFunc(element_type):
+ elements_xpath = PLCOpen_XPath(
+ "ppx:types/ppx:%(element_type)ss/ppx:%(element_type)s[@name=$name]" % locals())
+ def gettypeElement(self, name):
+ elements = elements_xpath(self, name=name)
+ if len(elements) == 1:
+ return elements[0]
+ return None
+ return gettypeElement
+
+ datatypes_xpath = PLCOpen_XPath("ppx:types/ppx:dataTypes/ppx:dataType")
+ filtered_datatypes_xpath = PLCOpen_XPath(
+ "ppx:types/ppx:dataTypes/ppx:dataType[@name!=$exclude]")
def getdataTypes(self, exclude=None):
- return self.xpath(
- "ppx:types/ppx:dataTypes/ppx:dataType%s" %
- ("[@name!='%s']" % exclude if exclude is not None else ""),
- namespaces=PLCOpenParser.NSMAP)
+ if exclude is not None:
+ return filtered_datatypes_xpath(self, exclude=exclude)
+ return datatypes_xpath(self)
setattr(cls, "getdataTypes", getdataTypes)
- def getdataType(self, name):
- return self.gettypeElement("dataType", name)
- setattr(cls, "getdataType", getdataType)
+ setattr(cls, "getdataType", gettypeElementFunc("dataType"))
def appenddataType(self, name):
if self.getdataType(name) is not None:
@@ -339,19 +340,17 @@
self.types.removedataTypeElement(name)
setattr(cls, "removedataType", removedataType)
- def getpous(self, exclude=None, filter=None):
+ def getpous(self, exclude=None, filter=[]):
return self.xpath(
"ppx:types/ppx:pous/ppx:pou%s%s" %
(("[@name!='%s']" % exclude) if exclude is not None else '',
("[%s]" % " or ".join(
map(lambda x: "@pouType='%s'" % x, filter)))
- if filter is not None else ""),
+ if len(filter) > 0 else ""),
namespaces=PLCOpenParser.NSMAP)
setattr(cls, "getpous", getpous)
- def getpou(self, name):
- return self.gettypeElement("pou", name)
- setattr(cls, "getpou", getpou)
+ setattr(cls, "getpou", gettypeElementFunc("pou"))
def appendpou(self, name, pou_type, body_type):
self.types.appendpouElement(name, pou_type, body_type)
@@ -365,18 +364,17 @@
self.types.removepouElement(name)
setattr(cls, "removepou", removepou)
+ configurations_xpath = PLCOpen_XPath(
+ "ppx:instances/ppx:configurations/ppx:configuration")
def getconfigurations(self):
- return self.getconfiguration()
+ return configurations_xpath(self)
setattr(cls, "getconfigurations", getconfigurations)
- def getconfiguration(self, name=None):
- configurations = self.xpath(
- "ppx:instances/ppx:configurations/ppx:configuration%s" %
- ("[@name='%s']" % name if name is not None else ""),
- namespaces=PLCOpenParser.NSMAP)
- if name is None:
- return configurations
- elif len(configurations) == 1:
+ configuration_xpath = PLCOpen_XPath(
+ "ppx:instances/ppx:configurations/ppx:configuration[@name=$name]")
+ def getconfiguration(self, name):
+ configurations = configuration_xpath(self, name=name)
+ if len(configurations) == 1:
return configurations[0]
return None
setattr(cls, "getconfiguration", getconfiguration)
@@ -395,12 +393,11 @@
raise ValueError, ("\"%s\" configuration doesn't exist !!!") % name
self.instances.configurations.remove(configuration)
setattr(cls, "removeconfiguration", removeconfiguration)
-
+
+ resources_xpath = PLCOpen_XPath(
+ "ppx:instances/ppx:configurations/ppx:configuration[@name=$configname]/ppx:resource[@name=$name]")
def getconfigurationResource(self, config_name, name):
- resources = self.xpath(
- "ppx:instances/ppx:configurations/ppx:configuration[@name='%s']/ppx:resource[@name='%s']" %
- (config_name, name),
- namespaces=PLCOpenParser.NSMAP)
+ resources = resources_xpath(self, configname=config_name, name=name)
if len(resources) == 1:
return resources[0]
return None
@@ -460,12 +457,10 @@
configuration.removeVariableByFilter(address_model)
setattr(cls, "removeVariableByFilter", removeVariableByFilter)
+ enumerated_values_xpath = PLCOpen_XPath(
+ "ppx:types/ppx:dataTypes/ppx:dataType/ppx:baseType/ppx:enum/ppx:values/ppx:value")
def GetEnumeratedDataTypeValues(self):
- return [
- value.getname()
- for value in self.xpath(
- "ppx:types/ppx:dataTypes/ppx:dataType/ppx:baseType/ppx:enum/ppx:values/ppx:value",
- namespaces=PLCOpenParser.NSMAP)]
+ return [value.getname() for value in enumerated_values_xpath(self)]
setattr(cls, "GetEnumeratedDataTypeValues", GetEnumeratedDataTypeValues)
def Search(self, criteria, parent_infos=[]):
@@ -982,9 +977,10 @@
pass
setattr(cls, "updateElementName", updateElementName)
+ enumerated_datatype_values_xpath = PLCOpen_XPath("ppx:values/ppx:value")
def Search(self, criteria, parent_infos=[]):
search_result = []
- for i, value in enumerate(self.xpath("ppx:values/ppx:value", namespaces=PLCOpenParser.NSMAP)):
+ for i, value in enumerate(enumerated_datatype_values_xpath(self)):
for result in TestTextElement(value.getname(), criteria):
search_result.append((tuple(parent_infos + ["value", i]),) + result)
return search_result
@@ -1000,6 +996,10 @@
cls = PLCOpenParser.GetElementClass("pou", "pous")
if cls:
+ block_inputs_xpath = PLCOpen_XPath(
+ "ppx:interface/*[self::ppx:inputVars or self::ppx:inOutVars]/ppx:variable")
+ block_outputs_xpath = PLCOpen_XPath(
+ "ppx:interface/*[self::ppx:outputVars or self::ppx:inOutVars]/ppx:variable")
def getblockInfos(self):
block_infos = {
"name" : self.getname(),
@@ -1015,16 +1015,12 @@
if return_type is not None:
block_infos["outputs"].append(
("OUT", _getvariableTypeinfos(return_type), "none"))
- for var in self.xpath(
- "ppx:interface/*[self::ppx:inputVars or self::ppx:inOutVars]/ppx:variable",
- namespaces=PLCOpenParser.NSMAP):
- block_infos["inputs"].append(
- (var.getname(), _getvariableTypeinfos(var.type), "none"))
- for var in self.xpath(
- "ppx:interface/*[self::ppx:outputVars or self::ppx:inOutVars]/ppx:variable",
- namespaces=PLCOpenParser.NSMAP):
- block_infos["outputs"].append(
- (var.getname(), _getvariableTypeinfos(var.type), "none"))
+ block_infos["inputs"].extend(
+ [(var.getname(), _getvariableTypeinfos(var.type), "none")
+ for var in block_inputs_xpath(self)])
+ block_infos["outputs"].extend(
+ [(var.getname(), _getvariableTypeinfos(var.type), "none")
+ for var in block_outputs_xpath(self)])
block_infos["usage"] = ("\n (%s) => (%s)" %
(", ".join(["%s:%s" % (input[1], input[0])
@@ -1610,10 +1606,12 @@
else:
raise TypeError, _("%s body don't have instances!")%self.content.getLocalTag()
setattr(cls, "getcontentInstances", getcontentInstances)
-
+
+ instance_by_id_xpath = PLCOpen_XPath("*[@localId=$localId]")
+ instance_by_name_xpath = PLCOpen_XPath("ppx:block[@instanceName=$name]")
def getcontentInstance(self, local_id):
if self.content.getLocalTag() in ["LD","FBD","SFC"]:
- instance = self.content.xpath("*[@localId=%d]" % local_id)
+ instance = instance_by_id_xpath(self.content, localId=local_id)
if len(instance) > 0:
return instance[0]
return None
@@ -1636,7 +1634,7 @@
def getcontentInstanceByName(self, name):
if self.content.getLocalTag() in ["LD","FBD","SFC"]:
- instance = self.content.xpath("ppx:block[@instanceName=%s]" % name, namespaces=PLCOpenParser.NSMAP)
+ instance = instance_by_name_xpath(self.content)
if len(instance) > 0:
return instance[0]
return None
@@ -1646,7 +1644,7 @@
def removecontentInstance(self, local_id):
if self.content.getLocalTag() in ["LD","FBD","SFC"]:
- instance = self.content.xpath("*[@localId=%d]" % local_id)
+ instance = instance_by_id_xpath(self.content)
if len(instance) > 0:
self.content.remove(instance[0])
else:
@@ -2533,13 +2531,14 @@
self.content = None
setattr(cls, "removeconnections", removeconnections)
+ connection_xpath = PLCOpen_XPath("ppx:connection")
+ connection_by_position_xpath = PLCOpen_XPath("ppx:connection[position()=$pos]")
def getconnections(self):
- return self.xpath("ppx:connection", namespaces=PLCOpenParser.NSMAP)
+ return connection_xpath(self)
setattr(cls, "getconnections", getconnections)
def getconnection(self, idx):
- connection = self.xpath("ppx:connection[position()=%d]" % (idx + 1),
- namespaces=PLCOpenParser.NSMAP)
+ connection = connection_by_position_xpath(self, pos=idx+1)
if len(connection) > 0:
return connection[0]
return None
--- a/xmlclass/xmlclass.py Tue Sep 03 23:39:22 2013 +0200
+++ b/xmlclass/xmlclass.py Thu Sep 05 10:36:33 2013 +0200
@@ -666,28 +666,20 @@
choices_dict[choice_name] = infos
choices_xpath = "|".join(map(lambda x: "%s:%s" % (factory.TargetNamespace, x), choices_dict.keys()))
- def GetContentChoicesXPath():
- return choices_xpath
-
def GetContentInitial():
content_name, infos = choices[0]
if content_name == "sequence":
content_value = []
for i in xrange(infos["minOccurs"]):
for element_infos in infos["elements"]:
- value = GetElementInitialValue(factory, element_infos)
- if value is not None:
- if element_infos["type"] == CHOICE:
- content_value.append(value)
- else:
- content_value.append({"name": element_infos["name"], "value": value})
+ content_value.extend(GetElementInitialValue(factory, element_infos))
else:
content_value = GetElementInitialValue(factory, infos)
- return {"name": content_name, "value": content_value}
+ return content_value
return {
"type": COMPLEXTYPE,
- "choices_xpath": GetContentChoicesXPath,
+ "choices_xpath": etree.XPath(choices_xpath, namespaces=factory.NSMAP),
"initial": GetContentInitial,
}
@@ -1212,7 +1204,7 @@
element_infos = elements[name]
element_infos["elmt_type"] = FindTypeInfos(factory, element_infos["elmt_type"])
if element_infos["type"] == CHOICE:
- content = self.xpath(element_infos["elmt_type"]["choices_xpath"](), namespaces=factory.NSMAP)
+ content = element_infos["elmt_type"]["choices_xpath"](self)
if element_infos["maxOccurs"] == "unbounded" or element_infos["maxOccurs"] > 1:
return content
elif len(content) > 0:
@@ -1261,7 +1253,7 @@
else:
element_xpath = ("%s:%s" % (factory.TargetNamespace, name)
if name != "content"
- else elements["content"]["elmt_type"]["choices_xpath"]())
+ else elements["content"]["elmt_type"]["choices_xpath"].path)
for element in self.xpath(element_xpath, namespaces=factory.NSMAP):
self.remove(element)
@@ -1272,7 +1264,7 @@
previous_elements_xpath = "|".join(map(
lambda x: "%s:%s" % (factory.TargetNamespace, x)
if x != "content"
- else elements["content"]["elmt_type"]["choices_xpath"](),
+ else elements["content"]["elmt_type"]["choices_xpath"].path,
elements.keys()[:element_idx]))
insertion_point = len(self.xpath(previous_elements_xpath, namespaces=factory.NSMAP))