简体   繁体   English

如何使用不断变化的XML

[英]How to consume constantly changing XML

Scenario: 场景:

Input: 输入:

  • An XML file whose structure constantly changes on the mercy of external team. 一个XML文件,其结构不断变化,受外部团队的影响。
  • It's not a well formed XML. 它不是一个格式良好的XML。
  • Element Tags change too sometime. 元素标签有时会改变。

Required Output: 要求输出:

  • A Object of predefined class which used by other parts of the application 由应用程序的其他部分使用的预定义类的Object

Problem: 问题:

  • How do i map Changing Element tags with fixed Class names. 如何使用固定的类名映射Changing Element标签。

C# language. C#语言。

enter code here
ReadIn("input.xml");

public static GbtInfo ReadIn(string path)
    {
        using (XmlReader reader = new XmlTextReader(path))
        {
            reader.ReadToDescendant("SYSTEM");
            return Serializers.ParseNode<GbtInfo>(reader);
        }
    }

public static T ParseNode<T>(XmlReader reader)
{
    Type t = typeof(T);
    return (T)ParseNode(t, reader);
}

public static object ParseNode(Type type, XmlReader reader)
{
    var instance = Activator.CreateInstance(type);

    IXmlSerializable xmlSerializable = instance as IXmlSerializable;
    if (xmlSerializable != null)
    xmlSerializable.ReadXml(reader);
    return instance;
}

public static object ParseNode(string name_space, string elementName, XmlReader reader)
{
    Type t = Type.GetType(name_space + "." + elementName, false, true);
    return ParseNode(t, reader);
}





public void ReadXml(System.Xml.XmlReader reader)
    {
        this.reader = reader;
        string nextElement;
        parent = reader.Name;
        PropertyInfo propertyinfo = null;

        //Setting a flag if the current node is empty.
        bool isEmptyElement = reader.IsEmptyElement;
        //Code that parses the attributes out of the Node.
        if (reader.HasAttributes)
        {
            for (int i = 0; i < reader.AttributeCount; i++)
            {
                reader.MoveToAttribute(i);
                nextElement = Utilities.RemoveSpecialChar(reader.Name);
                propertyinfo = (GetType()).GetProperty(nextElement, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                if (propertyinfo != null)
                    propertyinfo.SetValue(this, reader.Value, null);
                else
                    PrintError(nextElement);


            }
        }
        if (!isEmptyElement)//if the element is not empty get all the children 
        {
            reader.Read();
            Utilities.SkipToContent(reader);
            while (!(reader.Name.Equals(parent) && reader.NodeType == XmlNodeType.EndElement))
            {
                reader.MoveToContent();
                //Case when Node Element is an object type with string 
                if (reader.NodeType == XmlNodeType.Text)
                {
                    propertyinfo = (GetType()).GetProperty("Value", BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);

                    if (propertyinfo != null)
                        propertyinfo.SetValue(this, reader.Value, null);
                    else
                        PrintError("Value");

                    //Testing Console.WriteLine(nextelement + " => " + reader.Value);
                    reader.Read();
                    Utilities.SkipToContent(reader);
                }
                if (reader.NodeType == XmlNodeType.Element)
                {
                    nextElement = Utilities.RemoveSpecialChar(reader.Name);
                    propertyinfo = (GetType()).GetProperty(nextElement, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
                    if (propertyinfo != null)
                    {
                        if (propertyinfo.PropertyType.FullName.Equals("System.String"))
                        {
                            reader.Read();//read to get the text
                            if (reader.NodeType != XmlNodeType.Text)
                                throw new InvalidOperationException("Special Case encountered check XML");
                            propertyinfo.SetValue(this, reader.Value, null);
                            //Testing Console.WriteLine(reader.Value);
                            reader.ReadToNextSibling("dummy");//this will read to the parent end tag
                            reader.Read();
                            Utilities.SkipToContent(reader);
                        }
                        else
                        {

                            System.Collections.IList list = propertyinfo.GetValue(this, null) as System.Collections.IList;
                            if (list != null)
                            {
                                list.Add(Serializers.ParseNode(Namespace, nextElement, reader));

                            }
                            else
                            {
                                propertyinfo.SetValue(this, Serializers.ParseNode(Namespace, nextElement, reader), null);
                            }
                        }
                    }
                    else
                    {
                        PrintError(nextElement);
                        reader.ReadToNextSibling();
                    }
                }
            }
        }

        //move to the next element
        reader.Read();
        Utilities.SkipToContent(reader);
    }


    // Utilities Method

      private void PrintError(string errorElement)
        {
            IXmlLineInfo info = reader as IXmlLineInfo;
            Log.LogIt("The attribute " + errorElement + " does not exist under " + parent + " Error Occurred at Line "
                      + info.LineNumber + " Col " + info.LinePosition, LogMessageType.Warning);
            info = null;
    }

     public static XmlReader SkipToContent(XmlReader reader)
        {
            int count = 0;
            while (reader.NodeType != XmlNodeType.Element && reader.NodeType != XmlNodeType.Attribute &&
                   reader.NodeType != XmlNodeType.EndElement && reader.NodeType != XmlNodeType.Text)
            {
                reader.Read(); count++;
                if (count > 2)
                {
                    //Console.WriteLine(" Stuck");
                    if (reader.EOF)
                    {
                        break;
                    }
                }
            }
            return reader;
        }

/// <summary>
/// Removes special symbols like "-","_","." from Node element name inorder to match it with the respective objects. 
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static string RemoveSpecialChar(string str)
        {
            str = str.Replace("-", "");
            str = str.Replace(".", "");
            str = str.Replace("_", "");
            return str;
    }

First, you should force your external team to give you at least a syntactically correct XML file. 首先,您应该强制您的外部团队至少为您提供语法正确的XML文件。 This is an organizational issue, but if you cannot solve this, everything else does not make much sense. 这是一个组织问题,但如果你无法解决这个问题,其他一切都没有多大意义。

A Object of predefined class which used by other parts of the application 由应用程序的其他部分使用的预定义类的Object

Use an XmlDocument. 使用XmlDocument。 Access the content dynamically in your code, and deal with the situation when there is a missing tag or block at runtime. 在代码中动态访问内容,并在运行时缺少标记或块时处理这种情况。 Avoid mapping of element tags to statically defined attributes in a C# class as long as you don't know the element tag won't change any more in the next iteration. 只要您不知道元素标记在下一次迭代中不再更改,就避免将元素标记映射到C#类中的静态定义属性。 And if your code relies on some specific element tags, define them as string constants once in a central place in your code so you change them easily whenever a tag is renamed by the external team. 如果您的代码依赖于某些特定的元素标记,请在代码的中心位置将它们定义为字符串常量,以便在外部团队重命名标记时轻松更改它们。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM