Esempio n. 1
0
        /// <summary>
        /// Parse the XML for a term
        /// </summary>
        /// <param name="xmlReader"></param>
        /// <param name="ontologyEntries"></param>
        /// <param name="mostRecentTerm"></param>
        /// <param name="classIdentifier">Identifier from the owl:Class term</param>
        /// <returns>Term name</returns>
        private string ParseTerm(XmlReader xmlReader, ICollection <OwlEntry> ontologyEntries, string mostRecentTerm, string classIdentifier = "")
        {
            try
            {
                var identifier = classIdentifier;
                var name       = string.Empty;
                var definition = string.Empty;
                var comment    = string.Empty;

                var parentTerms = new Dictionary <string, OwlEntry.eParentType>();
                var synonyms    = new List <string>();

                var insideEquivalentClass = false;
                var insideIntersectionOf  = false;
                var insideSubClassOf      = false;
                var relationshipType      = string.Empty;

                var termParsed    = false;
                var startingDepth = xmlReader.Depth;

                while (xmlReader.Read())
                {
                    switch (xmlReader.NodeType)
                    {
                    case XmlNodeType.Element:
                        // Start element

                        switch (xmlReader.Name)
                        {
                        case "owl:Class":
                            if (insideIntersectionOf || insideEquivalentClass || insideSubClassOf)
                            {
                                break;
                            }

                            if (!string.IsNullOrWhiteSpace(classIdentifier))
                            {
                                OnWarningEvent("Nested owl:Class terms; this is unexpected. See term: " + classIdentifier);
                            }
                            else if (string.IsNullOrEmpty(name))
                            {
                                OnWarningEvent("Nested owl:Class terms; this is unexpected. Most recent term: " + mostRecentTerm);
                            }
                            else
                            {
                                OnWarningEvent("Nested owl:Class terms; this is unexpected. See term: " + name);
                            }
                            break;

                        case "owl:intersectionOf":
                            insideIntersectionOf = true;
                            break;

                        case "owl:equivalentClass":
                            insideEquivalentClass = true;
                            break;

                        case "rdfs:label":
                            name = xmlReader.ReadInnerXml();
                            break;

                        case "rdfs:subClassOf":
                            insideSubClassOf = true;
                            relationshipType = "part_of";

                            // Look for property rdf:resource
                            if (xmlReader.HasAttributes)
                            {
                                var parentURL = xmlReader.GetAttribute("rdf:resource");
                                if (GetItemFromURL(parentURL, out var parentTermId))
                                {
                                    AddParentTerm(parentTerms, "is_a", parentTermId, identifier);
                                }
                            }
                            else
                            {
                                // The subclass may have a restriction, e.g.
                                // <rdfs:subClassOf>
                                //     <owl:Restriction>
                                //         <owl:onProperty rdf:resource="http://purl.obolibrary.org/obo/bto#part_of"/>
                                //         <owl:someValuesFrom rdf:resource="http://purl.obolibrary.org/obo/BTO_0000439"/>
                                //     </owl:Restriction>
                                // </rdfs:subClassOf>
                                //
                                // We'll check for this when looking for element owl:someValuesFrom
                            }

                            break;

                        case "owl:onProperty":
                            if (insideSubClassOf && xmlReader.HasAttributes)
                            {
                                var parentURL = xmlReader.GetAttribute("rdf:resource");
                                if (GetItemFromURL(parentURL, out var relationshipTypeText))
                                {
                                    var poundIndex = relationshipTypeText.IndexOf("#", StringComparison.Ordinal);
                                    if (poundIndex >= 0)
                                    {
                                        relationshipType = relationshipTypeText.Substring(poundIndex + 1);
                                    }
                                    else
                                    {
                                        relationshipType = relationshipTypeText;
                                    }
                                }
                            }
                            break;

                        case "owl:someValuesFrom":
                            if (insideSubClassOf && xmlReader.HasAttributes)
                            {
                                var parentURL = xmlReader.GetAttribute("rdf:resource");
                                if (GetItemFromURL(parentURL, out var parentTermId))
                                {
                                    AddParentTerm(parentTerms, relationshipType, parentTermId, identifier);
                                }
                            }
                            break;

                        case "oboInOwl:id":
                            identifier = xmlReader.ReadInnerXml();
                            break;

                        case "oboInOwl:hasOBONamespace":
                            // Could parse out the name space
                            break;


                        case "oboInOwl:hasRelatedSynonym":
                            var synonym = xmlReader.ReadInnerXml();
                            synonyms.Add(synonym);
                            break;

                        case "obo:IAO_0000115":

                            definition = xmlReader.ReadInnerXml();
                            break;

                        case "rdfs:comment":
                            comment = xmlReader.ReadInnerXml();
                            break;
                        }

                        break;

                    case XmlNodeType.EndElement:
                        switch (xmlReader.Name)
                        {
                        case "rdfs:subClassOf":
                            insideSubClassOf = false;
                            break;

                        case "owl:intersectionOf":
                            insideIntersectionOf = false;
                            break;

                        case "owl:equivalentClass":
                            insideEquivalentClass = true;
                            break;
                        }

                        if (xmlReader.Depth == startingDepth)
                        {
                            termParsed = true;
                        }

                        break;

                    case XmlNodeType.Text:
                        // Important text should have already been skipped
                        break;
                    }

                    if (termParsed)
                    {
                        break;
                    }
                }

                var ontologyEntry = new OwlEntry(identifier, name)
                {
                    Definition = definition,
                    Comment    = comment
                };

                foreach (var parentEntry in parentTerms)
                {
                    ontologyEntry.AddParentTerm(parentEntry.Key, parentEntry.Value);
                }

                foreach (var synonym in synonyms)
                {
                    ontologyEntry.AddSynonym(synonym);
                }

                ontologyEntries.Add(ontologyEntry);

                return(name);
            }
            catch (Exception ex)
            {
                throw new Exception("Exception in ParseTerm: " + ex.Message, ex);
            }
        }