Обработка XML в MySQL в хорошем состоянии - PullRequest
0 голосов
/ 30 марта 2009

Мне нужно ежедневно обрабатывать документы XML различных форматов в записи в базе данных MySQL. Данные, которые мне нужны из каждого XML-документа, чередуются с большим количеством ненужных мне данных, и имена узлов каждого документа различны. Например:

источник № 1:

<object id="1">
    <title>URL 1</title>
    <url>http://www.one.com</url>
    <frequency interval="60" />
    <uselessdata>blah</uselessdata>
</object>
<object id="2">
    <title>URL 2</title>
    <url>http://www.two.com</url>
    <frequency interval="60" />
    <uselessdata>blah</uselessdata>
</object>

источник № 2:

<object">
    <objectid>1</objectid>
    <thetitle>URL 1</thetitle>
    <link>http://www.one.com</link>
    <frequency interval="60" />
   <moreuselessdata>blah</moreuselessdata>
</object>
<object">
    <objectid>2</objectid>
    <thetitle>URL 2</thetitle>
    <link>http://www.two.com</link>
    <frequency interval="60" />
    <moreuselessdata>blah</moreuselessdata>
</object>

... где мне нужны идентификатор объекта, интервал и URL.

Мои идеи для подходов:

1.) Наличие отдельной функции для анализа каждого XML-документа и итеративного создания SQL-запроса из этой функции

2.) Имея отдельную функцию, анализирую каждый документ и итеративно добавляю каждый объект в мой собственный класс объектов, и выполняю работу SQL с помощью метода класса

3.) Использование XSLT для преобразования всех документов в общий формат XML, а затем написание анализатора для этого документа.

Сами XML-документы не так уж и велики, так как большинство из них будут меньше 1 МБ. Я не ожидаю, что их структура будет часто меняться (если вообще когда-либо), но есть большая вероятность, что мне понадобится добавить и удалить дополнительные источники со временем. Я открыт для всех идей.

Кроме того, извините, если приведенные выше примеры XML искажены ... они не очень важны, просто грубая идея показать, что имена узлов в каждом документе разные.

Ответы [ 3 ]

2 голосов
/ 30 марта 2009

Использование XSLT является излишним. Мне нравится подход (2), он имеет большой смысл.

Используя Python, я бы попытался создать класс для каждого типа документа. Класс наследовал бы от dict и на его __init__ анализировал данный документ и заполнял себя 'id', 'interval' и 'url'.

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

0 голосов
/ 30 марта 2009

Если ваши различные форматы ввода однозначны, вы можете сделать это:

<xsl:template match="object">
  <object>
    <id><xsl:value-of select="@id | objectid" /></id>
    <title><xsl:value-of select="title | thetitle" /></title>
    <url><xsl:value-of select="url | link" /></url>
    <interval><xsl:value-of select="frequency/@interval" /></interval>
  </object>
</xsl:template>

Для вашего образца ввода это дает:

<object>
  <id>1</id>
  <title>URL 1</title>
  <url>http://www.one.com</url>
  <interval>60</interval>
</object>
<object>
  <id>2</id>
  <title>URL 2</title>
  <url>http://www.two.com</url>
  <interval>60</interval>
</object>
<object>
  <id>1</id>
  <title>URL 1</title>
  <url>http://www.one.com</url>
  <interval>60</interval>
</object>
<object>
  <id>2</id>
  <title>URL 2</title>
  <url>http://www.two.com</url>
  <interval>60</interval>
</object>

Однако могут быть более быстрые методы для достижения полезного результата, чем использование XSLT. Просто измерьте, насколько быстр каждый подход, и насколько "уродлив", если чувствуете себя для вас. Я бы сказал, что XSLT является более элегантным / поддерживаемым решением для обработки XML. YMMV.

Если ваши входные форматы неоднозначны и вышеприведенное решение дает неправильные результаты, требуется более явный подход, такой как:

<xsl:template match="object">
  <object>
    <xsl:choose>
      <xsl:when test="@id and title and url and frequency/@interval">
        <xsl:apply-templates select="." mode="format1" />
      </xsl:when>
      <xsl:when test="objectid and thetitle and link and frequency/@interval">
        <xsl:apply-templates select="." mode="format2" />
      </xsl:when>
    </xsl:choose>
  </object>
</xsl:template>

<xsl:template match="object" mode="format1">
  <id><xsl:value-of select="@id" /></id>
  <title><xsl:value-of select="title" /></title>
  <url><xsl:value-of select="url" /></url>
  <interval><xsl:value-of select="frequency/@interval" /></interval>
</xsl:template>

<xsl:template match="object" mode="format2">
  <id><xsl:value-of select="objectid" /></id>
  <title><xsl:value-of select="thetitle" /></title>
  <url><xsl:value-of select="link" /></url>
  <interval><xsl:value-of select="frequency/@interval" /></interval>
</xsl:template>
0 голосов
/ 30 марта 2009

Я успешно использую вариант третьего подхода. Но документы, которые я обрабатывал, были намного больше. Если это избыточное убийство или нет, это зависит от того, насколько хорошо вы владеете XSLT.

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