#c# #xml-parsing
#c# #xml-синтаксический анализ
Вопрос:
Для моего класса программирования на C # начального уровня мы, по сути, кодируем наш собственный анализатор XML (используя FileStream и ReadByte())
У нас есть «test.xml «файл, это идет… (мой учитель использует container взаимозаменяемо с родительским элементом и использует attribute в качестве дочернего элемента, он немного сбивает с толку тех из нас, кто немного разбирается в xml, но его класс предназначен для тех, кто не знает никакого xml)
<containers>
<container>
<attribute1>data for attribute1 of container1</attribute1>
<attribute2>data for attribute2 of container1</attribute2>
<attribute3>data for attribute3 of container1</attribute3>
</container>
///more containers with varying amounts of attributes
...
</containers>
Теперь в его примере синтаксического анализа (который мы должны изучить и создать нашу собственную версию, мы можем использовать его структуру, но он предпочитает, чтобы мы немного ее изменили) он использует константу
const string XMLCONTAINER = "container"
чтобы проверить, находимся ли мы внутри родительского элемента или обрабатываем дочерний элемент контейнера
if(!gInsideContainer) {
if(String.Compare(gParseToken,XMLCONTAINER)==0) {
Console.WriteLine("n***** BEG OF CONTAINERn");
gInsideContainer=true;
// save the offset of the beginning of the
// container into the container object
setAttribute("BEGPTR",gTagOffset.ToString());
}
Мне кажется, это плохая уловка, поскольку это означает, что я должен редактировать исходный код для каждого типа xml, который мы в конечном итоге обрабатываем, просто чтобы выяснить, находимся ли мы в родительском элементе или нет. Я пытаюсь подумать, учитывая код, который нам нужно изучить, как я могу выполнить более общую проверку, чтобы увидеть, нахожусь ли я внутри родительского элемента или я в дочернем элементе родительского элемента.
Я подумываю о создании массива для хранения открывающих элементов или другой строковой переменной для хранения текущего открывающего родительского элемента, а затем проверки его закрывающего элемента, но это может не сработать, поскольку способы, которые я собираюсь реализовать, перехватят начальный элемент
<containers>
и установите значение insideContainer равным true для остальной части синтаксического анализа (да, логические ошибки, по крайней мере, я могу определить это перед кодированием, хех)
Мне не разрешено использовать какой-либо класс синтаксического анализа .net XML (поскольку мы в основном переписываем его с меньшей функциональностью и, вероятно, менее эффективно, но это скорее опыт в решении проблем и создании алгоритмов, которому он стремится научить)
Есть предложения о том, как я мог бы реализовать свою идею? (и имейте в виду, здесь программист начального уровня, lol)
Большое спасибо за любую помощь и совет!
Ответ №1:
Более общий способ помещать ваш элемент в стек каждый раз, когда вы анализируете новый тег ввода, и извлекать верхний тег из стека при выходе. Если вам нужно знать, какой у вас родительский тег, вы можете заглянуть в него.
Еще лучше было бы создать древовидную структуру, где каждый узел содержит список дочерних узлов, и каждый дочерний узел содержит ссылку на своего родителя, что-то вроде
public class Node
{
public string Name {get; private set;}
public List<Node> Children {get;set;}
public Node Parent {get; private set}
public int ElementDepth
{
get{ return Parent == null ? 1 : Parent.Depth 1; }
}
public Node(string name, Node parent)
{
this.Name = name;
this.Children = new List<Node>();
this.Parent = parent;
}
public Node(byte[] xml, ref int startAt)
{
if(this.Depth == 2)
{
Console.WriteLine("In Container named "" this.Name """);
}
/* in this function:
* Get the tag name and either (recursively) create its children
* or return if it closes this tag
*/
}
}
затем в main все, что вам нужно сделать, это загрузить байты в память и вызвать Node(myArray, ref myIndexPointer)
, и если эта функция определена правильно, вы готовы.
Комментарии:
1. Это немного сбивает с толку, я на самом деле не так уж далеко продвинулся в ООП. Я конвертирую последовательную программу в очень простую ООП (для дополнительной оценки при преобразовании в ООП). в принципе, у меня есть класс xmlobject, который хранит элементы и значения данных (parallel arrays atm, но этот метод должен игнорировать исходные теги <containers> </containers>, поскольку они не имеют значений данных и являются корневым узлом) и класс XMLParse, который выполняет фактический синтаксический анализ. Сам этот класс вообще не входит в ООП (официально), поскольку он рассматривается в классе, который у меня в следующем семестре.
2. это один из недостатков просьбы о помощи в домашнем задании по SO … я попытаюсь конкретизировать это немного подробнее, но все же оставляю вам немного кода для написания.