def analyze(self): """ analyze() analyze will gather information about the nodes and references contained in a XML File to facilitate later preprocessing stages that adresss XML dependency issues returns: No return value """ nodeIds = [] ns = self.nodeset.getElementsByTagName("UANodeSet") # We need to find out what the namespace calls itself and other referenced, as numeric id's are pretty # useless sans linked nodes. There is two information sources... self.extractNamespaceURIs() # From <URI>...</URI> definitions for key in ns[0].attributes.keys(): # from xmlns:sX attributes if "xmlns:" in key: # Any key: we will be removing these qualifiers from Values later self.namespaceQualifiers.append(key.replace("xmlns:","")) if "xmlns:s" in key: # get a numeric nsId and modelname/uri self.namespaceOrder.append((int(key.replace("xmlns:s","")), ns[0].getAttribute(key))) # Get all nodeIds contained in this XML for nd in ns[0].childNodes: if nd.nodeType != nd.ELEMENT_NODE: continue if nd.hasAttribute(u'NodeId'): self.containedNodes.append( (opcua_node_id_t(nd.getAttribute(u'NodeId')), nd) ) refs = nd.getElementsByTagName(u'References')[0] for ref in refs.childNodes: if ref.nodeType == ref.ELEMENT_NODE: self.referencedNodes.append( (opcua_node_id_t(ref.firstChild.data), ref) ) logger.debug("Nodes: " + str(len(self.containedNodes)) + " References: " + str(len(self.referencedNodes)))
def preprocess_linkDependantModels(self): revertToStochastic = [] # (doc, int id), where id was not resolvable using model URIs # Attemp to identify the model relations by using model URIs in xmlns:sX or <URI> contents for doc in self.preProcDocuments: nsid = doc.getNamespaceId() dependencies = doc.getNamespaceDependencies() for d in dependencies: if d != nsid and d != 0: # Attempt to identify the namespace URI this d referes to... nsUri = doc.getReferencedNamespaceUri(d) # FIXME: This could actually fail and return ""! logger.info("Need a namespace referenced as " + str(d) + ". Which hopefully is " + nsUri) targetDoc = None for tgt in self.preProcDocuments: # That model, whose URI is known but its current id is not, will # refer have referred to itself as "1" if tgt.getReferencedNamespaceUri(1) == nsUri: targetDoc = tgt break if not targetDoc == None: # Found the model... relink the references doc.reassignReferencedNamespaceId(d, targetDoc.getNamespaceId()) continue else: revertToStochastic.append((doc, d)) logger.warn("Failed to reliably identify which XML/Model " + os.path.basename(doc.originXML) + " calls ns=" +str(d)) for (doc, d) in revertToStochastic: logger.warn("Attempting to find stochastic match for target namespace ns=" + str(d) + " of " + os.path.basename(doc.originXML)) # Copy all references to the given namespace refs = [] matches = [] # list of (match%, targetDoc) to pick from later for ref in doc.referencedNodes: if ref[0].ns == d: refs.append(opcua_node_id_t(str(ref[0]))) for tDoc in self.preProcDocuments: tDocId = tDoc.getNamespaceId() # Scenario: If these references did target this documents namespace... for r in refs: r.ns = tDocId r.toString() # ... how many of them would be found!? c = self.testModelCongruencyAgainstReferences(tDoc, refs) print(c) if c>0: matches.append((c, tDoc)) best = (0, None) for m in matches: print(m[0]) if m[0] > best[0]: best = m if best[1] != None: logger.warn("Best match (" + str(best[1]*100) + "%) for what " + os.path.basename(doc.originXML) + " refers to as ns="+str(d)+" was " + os.path.basename(best[1].originXML)) doc.reassignReferencedNamespaceId(d, best[1].getNamespaceId()) else: logger.error("Failed to find a match for what " + os.path.basename(doc.originXML) + " refers to as ns=" + str(d))
def analyze(self): """ analyze() analyze will gather information about the nodes and references contained in a XML File to facilitate later preprocessing stages that adresss XML dependency issues returns: No return value """ nodeIds = [] ns = self.nodeset.getElementsByTagName("UANodeSet") # We need to find out what the namespace calls itself and other referenced, as numeric id's are pretty # useless sans linked nodes. There is two information sources... self.extractNamespaceURIs() # From <URI>...</URI> definitions for key in ns[0].attributes.keys(): # from xmlns:sX attributes if "xmlns:" in key: # Any key: we will be removing these qualifiers from Values later self.namespaceQualifiers.append(key.replace("xmlns:", "")) if "xmlns:s" in key: # get a numeric nsId and modelname/uri self.namespaceOrder.append( (int(key.replace("xmlns:s", "")), re.sub("[A-Za-z0-9-_\.]+\.[xXsSdD]{3}$", "", ns[0].getAttribute(key)))) # Get all nodeIds contained in this XML for nd in ns[0].childNodes: if nd.nodeType != nd.ELEMENT_NODE: continue if nd.hasAttribute(u'NodeId'): self.containedNodes.append( (opcua_node_id_t(nd.getAttribute(u'NodeId')), nd)) refs = nd.getElementsByTagName(u'References')[0] for ref in refs.childNodes: if ref.nodeType == ref.ELEMENT_NODE: self.referencedNodes.append( (opcua_node_id_t(ref.firstChild.data), ref)) logger.debug("Nodes: " + str(len(self.containedNodes)) + " References: " + str(len(self.referencedNodes)))
def preprocess_linkDependantModels(self): revertToStochastic = [ ] # (doc, int id), where id was not resolvable using model URIs # Attemp to identify the model relations by using model URIs in xmlns:sX or <URI> contents for doc in self.preProcDocuments: nsid = doc.getNamespaceId() dependencies = doc.getNamespaceDependencies() for d in dependencies: if d != nsid and d != 0: # Attempt to identify the namespace URI this d referes to... nsUri = doc.getReferencedNamespaceUri( d) # FIXME: This could actually fail and return ""! logger.info("Need a namespace referenced as " + str(d) + ". Which hopefully is " + nsUri) targetDoc = None for tgt in self.preProcDocuments: # That model, whose URI is known but its current id is not, will # refer have referred to itself as "1" if tgt.getReferencedNamespaceUri(1) == nsUri: targetDoc = tgt break if not targetDoc == None: # Found the model... relink the references doc.reassignReferencedNamespaceId( d, targetDoc.getNamespaceId()) continue else: revertToStochastic.append((doc, d)) logger.warn( "Failed to reliably identify which XML/Model " + os.path.basename(doc.originXML) + " calls ns=" + str(d)) for (doc, d) in revertToStochastic: logger.warn( "Attempting to find stochastic match for target namespace ns=" + str(d) + " of " + os.path.basename(doc.originXML)) # Copy all references to the given namespace refs = [] matches = [] # list of (match%, targetDoc) to pick from later for ref in doc.referencedNodes: if ref[0].ns == d: refs.append(opcua_node_id_t(str(ref[0]))) for tDoc in self.preProcDocuments: tDocId = tDoc.getNamespaceId() # Scenario: If these references did target this documents namespace... for r in refs: r.ns = tDocId r.toString() # ... how many of them would be found!? c = self.testModelCongruencyAgainstReferences(tDoc, refs) print(c) if c > 0: matches.append((c, tDoc)) best = (0, None) for m in matches: print(m[0]) if m[0] > best[0]: best = m if best[1] != None: logger.warn("Best match (" + str(best[1] * 100) + "%) for what " + os.path.basename(doc.originXML) + " refers to as ns=" + str(d) + " was " + os.path.basename(best[1].originXML)) doc.reassignReferencedNamespaceId(d, best[1].getNamespaceId()) else: logger.error("Failed to find a match for what " + os.path.basename(doc.originXML) + " refers to as ns=" + str(d))