Чтение XML-файла / строки в общем виде без знания структуры

#c# #xml #linq #generics

#c# #xml #linq #общие сведения

Вопрос:

Я хочу прочитать иерархию XML в дереве объектов в памяти. Дерево XML может иметь n дочерних уровней. Я не знаю точного числа. Мои объекты в памяти имеют дочерние и родительские свойства, которые должны быть привязаны к элементу управления деревом.

Как я могу прочитать xml-файл / строку общим способом в мои объекты в памяти, когда я не знаю, как именно вызываются / записываются теги xml-элементов?

Например, кто-то может предоставить мне XML-структуру единиц, где каждая единица имеет много единиц и т.д… итак, я знаю, что xml-тег — это «unit», но это может быть и «module» или что-то еще … он должен работать в общем виде, но я не знаю, что спросить у пользователя, вводящего имя тега xml-элемента, например «unit».

Возможно ли это вообще, чего я хочу достичь?

Комментарии:

1. Вы, кажется, описываете концепцию DOM. Ваши общие объекты в памяти с дочерними и родительскими свойствами звучат точно так же, как узлы DOM.

2. Мои объекты в памяти — это ViewModels, являющиеся источником данных для элемента управления treeview

Ответ №1:

В любом случае, вы должны знать имя узла для анализа иерархии, по крайней мере, у вас должно быть определение. ИМХО, XElement это единственный универсальный XML синтаксический анализатор. Например, у вас есть XML, подобный этому:

 <module name="core">
    <modules>
        <module name="xml">
            <modules>
                <module name="reader" />
                <module name="writer" />
            </modules>
        </module>
        <module name="json">
            <modules>
                <module name="serializer" />
                <module name="deserializer" />
            </modules>
        </module>
    </modules>
</module>
 

Как я уже говорил ранее, у вас должны быть некоторые определения, такие как root node обязательное имя иерархического элемента и дочерний контейнер root node name s . Это один из простых способов, с помощью которого вы можете позволить своим пользователям указывать любые имена узлов, которые они пожелают, но с некоторыми ограничениями.

Вы можете проанализировать XML использование XElement следующим образом:

 XElement xElement = XElement.Load(@"pathtoyourxmlfile");
string rootNodeName = xElement.Name.LocalName;
IEnumerable<XElement> xElements = xElement.Descendants(rootNodeName   "s");
 

И, конечно, вы можете Linq xElements использовать и для анализа иерархии, которую вы можете повторить, чтобы построить свой элемент управления деревом.

Вы можете начать работу с XElement по этим ссылкам ниже:

Надеюсь, это помогло.

Комментарии:

1. Я знаю. Потомки и, похоже, ваш код будет работать 😉 Я последую вашему предложению: rootNodeName «s»); это нормально для меня, я думаю, СЕЙЧАС!

Ответ №2:

Я бы просто загрузил его, XmlDocument а затем построил проходящее дерево XmlNodes .

Комментарии:

1. @Jakuk если я не знаю XML-файл клиента и его структуру, было бы безумием просто читать каждый узел и предполагать, что я все делаю правильно… прежде всего, откуда я мог бы узнать имя тегов xml-элемента?

2. @msfanboy — либо вы знаете имена узлов и хотите читать только их, либо вы их не знаете и хотите прочитать весь файл. Другого способа нет. Вы спросили how to read xml file in a generic way when nodes are not known . Если вы хотите получить другой ответ, задайте другой вопрос

Ответ №3:

Я считаю, что можно достичь того, чего вы хотите достичь. Я бы сделал это примерно так:

 class GenericNode
{
  private List<GenericNode> _Nodes = new List<GenericNode>();
  private List<GenericKeyValue> _Attributes = new List<GenericKeyValue>();
  public GenericNode(XElement Element)
  {
     this.Name = Element.Name;
     this._Nodes.AddRange(Element.Elements()
                                 .Select(e => New GenericNode(e));
     this._Attributes.AddRange(
                Element.Attributes()
                       .Select(a => New GenericKeyValue(a.Key, a.Value))
  }

  public string Name { get; private set; }
  public IEnumerable<GenericNode> Nodes
  {
    get
    {
       return this._Nodes;
    }       
  }
  public IEnumerable<GenericKeyValue> Attributes
  {
    get
    {
       return this._Attributes;
    }
  }
}

class GenericKeyValue
{
  public GenericKeyValue(string Key, string Value)
  {
     this.Key = Key;
     this.Value = Value;
  }
  public string Key { get; set; }
  public string Value { get; set; }
}
 

Затем вы просто:

 XElement rootElement = XElement.Parse(StringOfXml); // or
XElement rootElement = XElement.Load(FileOfXml);

GenericNode rootNode = new GenericRode(rootElement);
 

Ответ №4:

Взгляните на XmlTextReader и на пакет System.Xml . Эти статьи также помогут вам:

Ответ №5:

Нравится это?

 using System.Xml ;
using System.IO;
class Program
{
  static void Main( string[] args )
  {
    using ( Stream inputStream = OpenXmlStream() )
    {
      XmlDocument document = new XmlDocument() ;
      document.Load( inputStream ) ;
      Process( document ) ;
    }
  }
  static Stream OpenXmlStream()
  {
    // provide an input stream for the program
  }
  static void Process( XmlDocument document )
  {
    // do something useful here
  }
}