Хранение реляционных данных в XML - PullRequest
1 голос
/ 26 сентября 2008

Мне интересно, каковы лучшие методы хранения реляционной структуры данных в XML. В частности, мне интересно узнать о лучших методах обеспечения порядка узлов. Например, скажем, у меня есть три объекта: School, Course и Student, которые определены следующим образом:

class School
{
    List<Course> Courses;
    List<Student> Students;
}

class Course
{
    string Number;
    string Description;
}

class Student
{
    string Name;
    List<Course> EnrolledIn;
}

Я бы сохранил такую ​​структуру данных в XML примерно так:

<School>
    <Courses>
        <Course Number="ENGL 101" Description="English I" />
        <Course Number="CHEM 102" Description="General Inorganic Chemistry" />
        <Course Number="MATH 103" Description="Trigonometry" />
    </Courses>
    <Students>
        <Student Name="Jack">
            <EnrolledIn>
                <Course Number="CHEM 102" />
                <Course Number="MATH 103" />
            </EnrolledIn>
        </Student>
        <Student Name="Jill">
            <EnrolledIn>
                <Course Number="ENGL 101" />
                <Course Number="MATH 103" />
            </EnrolledIn>
        </Student>
    </Students>
</School>

С XML, упорядоченным таким образом, я могу сначала проанализировать Courses. Затем, когда я анализирую Students, я могу найти каждый Course, указанный в EnrolledIn (по Number) в списке School.Courses. Это даст мне ссылку на объект для добавления в список EnrolledIn в Student. Однако, если Students предшествует до Courses, такой поиск для получения ссылки на объект невозможен. (Поскольку School.Courses еще не заселено.)

Так, каковы лучшие практики для хранения реляционных данных в XML? - Должен ли я требовать, чтобы Courses всегда предшествовал Students? - Должен ли я терпеть любое упорядочение и создавать объект-заглушку Course всякий раз, когда сталкиваюсь с тем, кого еще не видел? (Будет расширено, когда определение Course будет в конце концов достигнуто.) - Есть ли какой-то другой способ, которым я должен сохранять / загружать свои объекты в / из XML? (В настоящее время я внедряю методы Save и Load для всех своих бизнес-объектов и делаю все это вручную, используя System.Xml.XmlDocument и связанные с ним классы.)

Я привык работать с реляционными данными из SQL, но это мой первый опыт попытки сохранить нетривиальную структуру реляционных данных в XML. Будем весьма благодарны за любые советы, которые вы можете дать относительно того, как мне поступить.

Ответы [ 8 ]

2 голосов
/ 27 сентября 2008

Не думайте о SQL или реляционном при работе с XML, потому что нет ограничений по порядку.

Однако вы можете в любое время запросить с помощью XPath любую часть документа XML. Сначала вы хотите курсы, а затем "// Курсы / Курс". Вы хотите, чтобы зачисление студентов было следующим, а затем "//Students/Student/EnrolledIn/Course".

Суть в том, что ... только потому, что XML хранится в файле, не поймайте себя на том, что все ваши обращения последовательны.


Я опубликовал отдельный вопрос, «Может ли XPath выполнить поиск по внешнему ключу по двум поддеревьям XML?» , чтобы уточнить мою позицию. Решение показывает, как вы можете использовать XPath для выполнения реляционных запросов к данным XML.

2 голосов
/ 27 сентября 2008

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

Лучше всего проанализировать все ваши данные и затем выполнить необходимые действия. Не действовать во время разбора.


Очевидно, что структура XML и данные за ним не позволяют сериализовать один POCO в XML. Вам необходимо управлять логикой сериализации и десериализации, чтобы отсоединять и перехватывать объекты вместе.

Я бы предложил создать пользовательский сериализатор, который создает xml-представление этого графа объектов. Таким образом, он может контролировать не только порядок сериализации, но и обрабатывать ситуации, когда узлы находятся не в ожидаемом порядке. Вы могли бы делать другие вещи, такие как добавление пользовательских атрибутов для использования для связывания объектов, которые не существуют в качестве открытых свойств сериализуемых объектов.

Создание xml будет таким же простым, как итерация по вашим объектам несколько раз, создание коллекций XElements с ожидаемым представлением объектов в виде xml. Когда вы закончите, вы можете сшить их вместе в XDocument и взять из него xml. Вы можете сделать несколько проходов через xml на обратной стороне, чтобы заново создать свой граф объектов и восстановить все ссылки.

1 голос
/ 27 сентября 2008

Порядок узлов важен только в том случае, если вам нужно обрабатывать данные только вперед, например, используя XmlReader или SAX-парсер. Если вы собираетесь прочитать XML в DOM перед его обработкой (что вы и делаете, если используете XmlDocument), порядок узлов на самом деле не имеет значения. Что еще важнее, так это то, что XML структурирован так, чтобы вы могли эффективно запрашивать его с помощью XPath, т.е. без использования "//".

Если вы посмотрите на схему, которую создает DataSetGenerator, вы увидите, что нет никакого порядка, связанного с элементами уровня DataTable. Может случиться так, что ADO обрабатывает элементы в некоторой последовательности, не представленной в схеме (например, один DataTable за один раз), или это может быть то, что ADO выполняет обработку только вперед и не применяет реляционные ограничения, пока DataSet не будет полностью прочитан. Я не знаю. Но ясно, что ADO не связывает порядок обработки с порядком документов.

(И да, вы можете указать порядок дочерних элементов в схеме XML; это то, что делает xs: sequence. Если вы не хотите, чтобы порядок узлов был принудительно установлен, вы используете неограниченный xs: choice.)

0 голосов
/ 27 сентября 2008

Я уже давно, но мне кажется, что я помню, как делал базовую коллекцию «вещей» в одной части XML-файла и обращался к ним в другой, используя функции схемы keyref и см . Я нашел несколько примеров здесь . Приношу свои извинения, если это не то, что вы ищете.

0 голосов
/ 27 сентября 2008

Вы также можете использовать два XML-файла, один для курсов и второй для студентов. Откройте и проанализируйте первый, прежде чем делать второй.

0 голосов
/ 27 сентября 2008

XML определенно не подходит для реляционных данных.

Если вам абсолютно необходимо это сделать, то я бы рекомендовал фанки перевернутую логику.

В вашем примере у вас есть школы, которые предлагают много курсов, которые посещают многие студенты.

Ваш XML может выглядеть следующим образом:

<School>
    <Students>
        <Student Name="Jack">
            <EnrolledIn>
                <Course Number="CHEM 102" Description="General Inorganic Chemistry" />
                <Course Number="MATH 103" Description="Trigonometry" />
            </EnrolledIn>
        </Student>
        <Student Name="Jill">
            <EnrolledIn>
                <Course Number="ENGL 101" Description="English I" />
                <Course Number="MATH 103" Description="Trigonometry" />
            </EnrolledIn>
        </Student>
    </Students>
</School>

Это, очевидно, не самый повторяющийся способ сделать это (это реляционные данные!), Но он легко разбирается.

0 голосов
/ 27 сентября 2008

Порядок обычно не важен в XML. В этом случае Courses может идти после Students. Вы анализируете XML, а затем выполняете запросы ко всем данным.

0 голосов
/ 27 сентября 2008

По опыту, XML не лучший способ хранения реляционных данных. Вы исследовали YAML ? У вас есть возможность?

Если вы этого не сделаете, безопасным способом было бы иметь строгий DTD для XML и применять его таким образом. Вы также можете, как вы предлагаете, сохранить хэш созданных объектов. Таким образом, если Студент создает Курс, вы сохраняете этот Курс для последующего обновления, когда нажмете тег.

Также помните, что вы можете использовать запросы XPath для прямого доступа к конкретным узлам, поэтому вы можете сначала выполнить анализ курсов независимо от положения в документе XML. (делая более полный ответ, спасибо дакрако)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...