Вопрос о том, как найти ассоциации в файле XML? - PullRequest
0 голосов
/ 08 декабря 2018

Я пытаюсь найти ассоциации между классами в проекте.

context: Я использую инфраструктуру System.Xml в c # для доступа к XML-файлу и получения необходимой информации.После этого я создаю файл JSON, который должен выглядеть следующим образом:

{
  "data": [
    {
      "name": "<Class>",
      "attributes": [
        {
          "name": "<name>",
          "type": "<type>"
        }
      ],
      "methods": [
        {
          "name": "<name>",
          "returnType": "<returnType>"
        }
      ],
      "subclasses": [
        "<Class>",
        "<Class>"
      ],
      "components": [
        "<Class>",
        "<Class>"
      ],
      "associations": [
        "<Class>",
        "<Class>"
      ]
    }
  ]
}

Мне удалось создать массив данных, имя класса, его атрибуты, их типы и, наконец, методы.Следующим шагом является получение остатка, в котором я застрял.

Это то, что я сделал до сих пор:

PS: (это не показывает мою попытку решить проблему, потому что я действительно не уверен, с чего начать.)

 using Newtonsoft.Json;
 using System;
 using System.IO;
 using System.Xml;

 [Serializable]

 class Program
  {
    protected static void Main(string[] args)
     {
      XmlDocument xmlBefore, xmlAfter;
      //XmlNodeList attr, meth;
       XmlNode name, attributes, methods; // superClasses, subClasses, 
  components, associations; //<-- these are our constraints

    //Create an xml doc for existing file
    xmlBefore = new XmlDocument();
    //load project
    xmlBefore.Load("../../../../assets/tests/sample/singleClass.xml");
    XmlNode root = xmlBefore.DocumentElement;

    //this is needed to make xpath queries
    XmlNamespaceManager namespaceManager = new XmlNamespaceManager(xmlBefore.NameTable);
    namespaceManager.AddNamespace("src", "http://www.srcML.org/srcML/src");

    name = GetClassName(xmlBefore, namespaceManager);
    attributes = GetAttributes(xmlBefore, namespaceManager);
    methods = GetMethods(xmlBefore, namespaceManager);

    xmlAfter = new XmlDocument();
    XmlNode data, className, classAttributes, classMethods;

    className = ImportNode(name, xmlBefore, xmlAfter);
    classAttributes = ImportNode(attributes, xmlBefore, xmlAfter);
    classMethods = ImportNode(methods, xmlBefore, xmlAfter);

    data = xmlAfter.CreateElement("data");
    data.AppendChild(className);
    data.AppendChild(classAttributes);
    data.AppendChild(classMethods);

    xmlAfter.AppendChild(data); Console.WriteLine(xmlAfter.InnerXml);

    /***** Will use later *****/
    try
    {
        String path = "../../../../assets/xml2json.json";
        // serialize JSON to a string and then write string to a file
        File.WriteAllText(path, JsonConvert.SerializeObject(xmlAfter));
        // serialize JSON directly to a file
        using (StreamWriter file = File.CreateText(path))
        {
            JsonSerializer serializer = new JsonSerializer();
            serializer.Serialize(file, xmlAfter);
        }
    }

    catch (Exception u)
    {
        Console.WriteLine(u.ToString());
    }

}

//----------------------------------------------------------------------------------------------------------------
//
//Methods 
//
//----------------------------------------------------------------------------------------------------------------

public static String XmlToJson(XmlDocument xmlFile)
{
    return JsonConvert.SerializeXmlNode(xmlFile);
}

/*Imports nodes in a list from one document to another */
public static XmlNode ImportNodes(XmlNodeList list, XmlDocument originDoc, XmlDocument destinationDoc)
{
    //you cant really just reference a node from one doc to another so you need to import them first

    //create a export node that stores import
    XmlNode exportNode = destinationDoc.CreateElement("exportNode");

    foreach (XmlNode node in list)
    {
        exportNode.AppendChild(destinationDoc.ImportNode(node, true));
    }
    return exportNode;
}

public static XmlNode ImportNode(XmlNode node, XmlDocument originDoc, XmlDocument destinationDoc)
{
    //you cant really just reference a node from one doc to another so you need to import them first

    return destinationDoc.ImportNode(node, true);
}

//----------------------------------------------------------------------------------------------------------------
//
//WARNING: hard coded teritorry yeeehhaaww
//the methods below are only reusable for OUR GROUP PROJECT (DIT3**)
//
//----------------------------------------------------------------------------------------------------------------

public static XmlNode GetClassName(XmlDocument xDoc, XmlNamespaceManager nsm)
{
    XmlNode classNameNode = xDoc.CreateElement("name");
    classNameNode = xDoc.DocumentElement.SelectSingleNode("/src:unit/src:class/src:name", nsm);
    return classNameNode;
}

public static XmlNode GetAttributes(XmlDocument xDoc, XmlNamespaceManager nsm)
{
    XmlNodeList attributeList = xDoc.DocumentElement.SelectNodes("/src:unit/src:class//src:decl_stmt//src:decl", nsm);
    XmlNode attributeNode = xDoc.CreateElement("attributes");

    //we only need type, name;
    foreach (XmlNode node in attributeList)
    {
        String type, name;
        //retrive the nodes we need and store their value
        type = node.SelectSingleNode("./src:type", nsm).InnerText;

        //if there is a final in a type string, remove it
        if (type.Length > 5 && type.Substring(0, 5).Equals("final"))
        {
            type = type.Substring(5, (type.Length - 5));
        }

        name = node.SelectSingleNode("./src:name", nsm).InnerText;

        //create a new element
        XmlElement attribute, typeElement, nameElement;
        typeElement = xDoc.CreateElement("type");
        typeElement.InnerText = type;

        nameElement = xDoc.CreateElement("name");
        nameElement.InnerText = name;

        attribute = xDoc.CreateElement("attribute");
        attribute.AppendChild(nameElement);
        attribute.AppendChild(typeElement);

        //append the child to the original node
        attributeNode.AppendChild(attribute);

    }
    return attributeNode;
}

public static XmlNode GetMethods(XmlDocument xDoc, XmlNamespaceManager nsm)
{
    XmlNodeList methodList = xDoc.DocumentElement.SelectNodes("/src:unit/src:class//src:function", nsm);
    XmlNode methodNode = xDoc.CreateElement("methods");

    //we only need type, name
    foreach (XmlNode node in methodList)
    {
        String type, name;
        //retrive the nodes we need and store their value
        type = node.SelectSingleNode("./src:type/src:name", nsm).InnerText;
        name = node.SelectSingleNode("./src:name", nsm).InnerText;

        //create elements
        XmlElement method, methodName, methodType;
        methodName = xDoc.CreateElement("name");
        methodName.InnerText = name;

        methodType = xDoc.CreateElement("type");
        methodType.InnerText = type;

        method = xDoc.CreateElement("method");
        method.AppendChild(methodName);
        method.AppendChild(methodType);

        //append results
        methodNode.AppendChild(method);
    }
    return methodNode;
}

public static XmlNode GetSubClasses(XmlNodeList list, XmlDocument originDoc, XmlDocument destinationDoc)
{
    return null;
}

public static XmlNode GetSuperClasses(XmlNodeList list, XmlDocument originDoc, XmlDocument destinationDoc)
{
    return null;
}

       public static XmlNode GetComponents(XmlNodeList list, XmlDocument 
       originDoc, 
     XmlDocument destinationDoc)
    {
        return null;
    }
  }

XML-файл, который я бы использовал (однако идея заключается в том, чтобы заставить его работать с любым XML):

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<unit xmlns="http://www.srcML.org/srcML/src" revision="0.9.5" language="Java" filename="Employee.java"><package> package         <name>assignment3</name>;</package>  

     <class><specifier>public</specifier> class <name>Employee</name>     <super><implements>implements <name><name>Comparable</name><argument_list type="generic">&lt;<argument><name>Employee</name></argument>&gt;</argument_list></name></implements></super><block>{

       <decl_stmt><decl><specifier>private</specifier> <type><specifier>final</specifier> <name>int</name></type> <name>EQUAL_RESULT</name> <init>= <expr><literal type="number">0</literal></expr></init></decl>;</decl_stmt>
     <decl_stmt><decl><specifier>private</specifier> <type><specifier>final</specifier> <name>int</name></type> <name>INVERSE</name> <init>= <expr><operator>-</operator><literal type="number">1</literal></expr></init></decl>;</decl_stmt>
     <decl_stmt><decl><specifier>private</specifier> <type><name>String</name></type> <name>name</name></decl>;</decl_stmt>
    <decl_stmt><decl><specifier>private</specifier> <type><name>String</name></type> <name>id</name></decl>;</decl_stmt>
    <decl_stmt><decl><specifier>private</specifier> <type><name>double</name></type> <name>grossSalary</name></decl>;</decl_stmt>
    <decl_stmt><decl><specifier>private</specifier> <type><specifier>final</specifier> <name>double</name></type> <name>TAX</name> <init>= <expr><literal type="number">0.1</literal></expr></init></decl>;</decl_stmt>
    <decl_stmt><decl><specifier>public</specifier> <specifier>static</specifier> <type><name>String</name></type> <name>choose</name></decl>;</decl_stmt>
    <decl_stmt><decl><specifier>public</specifier> <specifier>static</specifier> <type><name>String</name></type> <name>orderBy</name></decl>;</decl_stmt>



        <constructor><specifier>public</specifier> <name>Employee</name><parameter_list>(<parameter><decl><type><name>String</name></type> <name>name</name></decl></parameter>, <parameter><decl><type><name>String</name></type> <name>id</name></decl></parameter>, <parameter><decl><type><name>double</name></type> <name>grossSalary</name></decl></parameter>)</parameter_list> <block>{
        <expr_stmt><expr><name><name>this</name><operator>.</operator><name>name</name></name><operator>=</operator><name>name</name></expr>;</expr_stmt>
        <expr_stmt><expr><name><name>this</name><operator>.</operator><name>id</name></name><operator>=</operator><name>id</name></expr>;</expr_stmt>
        <expr_stmt><expr><name><name>this</name><operator>.</operator><name>grossSalary</name></name><operator>=</operator> <name>grossSalary</name></expr>;</expr_stmt>
     }</block></constructor>

        <comment type="block">/*
      * this method is to keep the getGrossSalary() from changing, 
      * so all the changes will affect calculateSalary() not      getGrossSalary().
       */</comment>
    <function><specifier>public</specifier> <type><name>double</name></type> <name>calculateSalary</name><parameter_list>()</parameter_list> <block>{ 
        <return>return <expr><name><name>this</name><operator>.</operator><name>grossSalary</name></name></expr>;</return>
    }</block></function>

    <function><specifier>public</specifier> <type><name>double</name></type> <name>getNetSalary</name><parameter_list>()</parameter_list> <block>{
        <return>return <expr><name><name>this</name><operator>.</operator><name>grossSalary</name></name><operator>-</operator> <operator>(</operator><name><name>this</name><operator>.</operator><name>grossSalary</name></name><operator>*</operator><name>TAX</name><operator>)</operator></expr>;</return>
    }</block></function>


    <function><annotation>@<name>Override</name></annotation>
    <specifier>public</specifier> <type><name>int</name></type> <name>compareTo</name><parameter_list>(<parameter><decl><type><name>Employee</name></type> <name>newEmployee</name></decl></parameter>)</parameter_list> <block>{
        <decl_stmt><decl><type><name>int</name></type> <name>result</name> <init>= <expr><call><name><name>this</name><operator>.</operator><name>getName</name></name><argument_list>()</argument_list></call><operator>.</operator><call><name>compareToIgnoreCase</name><argument_list>(<argument><expr><call><name><name>newEmployee</name><operator>.</operator><name>getName</name></name><argument_list>()</argument_list></call></expr></argument>)</argument_list></call></expr></init></decl>;</decl_stmt>
        <if>if <condition>(<expr><name>result</name> <operator>==</operator> <name>EQUAL_RESULT</name></expr>)</condition><then> <block>{
            <expr_stmt><expr><name>result</name> <operator>=</operator> <call><name><name>Double</name><operator>.</operator><name>compare</name></name><argument_list>(<argument><expr><call><name><name>this</name><operator>.</operator><name>getGrossSalary</name></name><argument_list>()</argument_list></call></expr></argument>, <argument><expr><call><name><name>newEmployee</name><operator>.</operator><name>getGrossSalary</name></name><argument_list>()</argument_list></call></expr></argument>)</argument_list></call></expr>;</expr_stmt>
        }</block></then></if>
        <return>return <expr><name>result</name></expr>;</return>
       }</block></function>



           <function><specifier>public</specifier> <type><name>String</name>    </type> <name>getName</name><parameter_list>()</parameter_list> <block>{
            <return>return <expr><name>name</name></expr>;</return>
            }</block></function>

        <function><specifier>public</specifier> <type><name>void</name></type> <name>setName</name><parameter_list>(<parameter><decl><type><name>String</name></type> <name>name</name></decl></parameter>)</parameter_list> <block>{
            <expr_stmt><expr><name><name>this</name><operator>.</operator><name>name</name></name> <operator>=</operator> <name>name</name></expr>;</expr_stmt>
        }</block></function>


        <function><specifier>public</specifier> <type><name>String</name></type> <name>getId</name><parameter_list>()</parameter_list> <block>{
            <return>return <expr><name>id</name></expr>;</return>
        }</block></function>

        <function><specifier>public</specifier> <type><name>double</name></type> <name>getGrossSalary</name><parameter_list>()</parameter_list> <block>{
            <return>return <expr><name>grossSalary</name></expr>;</return>
        }</block></function>

        <function><specifier>public</specifier> <type><name>void</name></type> <name>setGrossSalary</name><parameter_list>(<parameter><decl><type><name>double</name></type> <name>grossSalary</name></decl></parameter>)</parameter_list> <block>{
            <expr_stmt><expr><name><name>this</name><operator>.</operator><name>grossSalary</name></name><operator>=</operator><name>grossSalary</name></expr>;</expr_stmt>
        }</block></function>

    <function><specifier>public</specifier> <type><name>String</name></type> <name>toString</name><parameter_list>()</parameter_list> <block>{
        <return>return <expr><name><name>this</name><operator>.</operator><name>name</name></name><operator>+</operator><literal type="string">"'s gross Salary is of "</literal><operator>+</operator> <name><name>this</name><operator>.</operator><name>grossSalary</name></name><operator>+</operator><literal type="string">" SEK per month. "</literal></expr>;</return>
    }</block></function>
    <comment type="line">// CHALLENGE 1</comment>
        <comment type="block">/*@Override 

    */</comment>    

}</block></class>
</unit>
...