Генерация SQL с использованием XML и XSLT - PullRequest
1 голос
/ 26 ноября 2008

У меня есть определение XML, которое содержит элемент с дочерними элементами. Например:

<a>
 <b>
  <c>C</c>
  <d>D</d>
 </b>
</a>

У меня есть XSLT с выводом текста. Например:

<xsl...>
  <xsl:output method="text" indent="yes"/>
  <xsl:template match="/">
    <xsl:copy-of select="/a/b" />
  ...

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

select * from some-table where xml = '<b><c>C</c><d>D</d></b>'

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

Есть идеи?

Ответы [ 3 ]

1 голос
/ 26 ноября 2008

Возможно, это слишком сложная задача для XSLT. Самое близкое, что я могу получить, это:

  <xsl:template match="b//*|node()">
    <xsl:copy>
      <xsl:text>&lt;</xsl:text>
      <xsl:value-of select="name()"/>
      <xsl:text>&gt;</xsl:text>
      <xsl:value-of select="text()"/>
      <xsl:apply-templates select="*"/>
      <xsl:text>&lt;/</xsl:text>
      <xsl:value-of select="name()"/>
      <xsl:text>&gt;</xsl:text>
    </xsl:copy>
  </xsl:template>

И вызывается с помощью:

  <xsl:apply-templates select="/a/b/self::*"/>

Это производит следующее:

 <b>
  <c>C</c>
  <d>D</d>
 </b>

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

Есть идеи?

1 голос
/ 26 ноября 2008

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

Я полагаю, что и у Oracle (наверняка), и у SQL Server (думаю, так) есть механизмы для выполнения запроса к столбцу, содержащему XML, более дружественным для XML способом (например, с использованием XPath).

Что именно вы пытаетесь сделать? Ваша проблема кажется глубже, чем просто заставить этот XSLT преобразовываться правильно.

0 голосов
/ 26 ноября 2008

Вот как это можно сделать:

<xsl:output method="xml" />

<xsl:template match="/"><xsl:apply-templates select="/a/b" mode="normalize-space" /></xsl:template>

<xsl:template match="text()" mode="normalize-space"><xsl:value-of select="normalize-space(.)" /></xsl:template>
<xsl:template match="@*|node()" mode="normalize-space"><xsl:copy><xsl:apply-templates select="@*|node()" mode="normalize-space" /></xsl:copy></xsl:template>

Этот метод копирует узлы, узлы с пространствами имен и атрибутами.

Метод требует, чтобы выходные данные были «xml» (а не «text», как в исходном образце). Он использует пользовательский шаблон для всех узлов TEXT, чтобы нормализовать пространство внутри них (удалить начальные / конечные пробелы, объединить несколько пробелов в один пробел). Затем он использует простой «идентификационный» шаблон, который копирует все узлы и их атрибуты. Оба шаблона используют специальный режим, чтобы не мешать остальному XSL.

К сожалению, процессор XSLT копирует все «неизвестные» узлы внутри тега xsl: template в выходной документ, и пробелы являются одним из таких узлов. Вот почему все эти шаблоны должны быть записаны в одну строку без лишних пробелов.

PS Хотя я согласен с тем, что поиск нормализованного XML в СУБД довольно странен.

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