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)))
Example #4
0
    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))