Гость
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / xsl шаблон для кодогенератора / 5 сообщений из 5, страница 1 из 1
23.06.2012, 15:07
    #37851461
Максим Н
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
xsl шаблон для кодогенератора
Делаю небольшой PLSQL кодогенератор API для таблиц БД. Процедуры обертки для insert, update, delete, exist и прочей механики. Готовые решения есть, но мне не нравятся, гибкости не хватает - чтобы банально изменить формитирование кода нужно лезть в код, выдерать куски и т.д., т.е. неудобно. Появилась идея аккуратно сделать это с помощью xsl-шаблонов, генерировать нужный код на основе xml-описаня таблиц, т.е. из этого:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
   <table name="contents" type="normal">
      <columns>
         <column name="id" type="NUMBER" />
         <column name="title" type="VARCHAR2" />
         <column name="text" type="CLOB" />
      </columns>
      <pk>
         <column name ="id" />
      </pk>
   </table>


Нужно получить примерно это:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
CREATE OR REPLACE PACKAGE contents_API
/*******************************
* API Package for "contents" table
*******************************/

PROCEDURE ins(
	id_i contents.id%TYPE;
	title_i contents.title%TYPE;
	text_i contents.text%TYPE;

)
IS
BEGIN
 	INSERT INTO contents (
		id,
		title,
		text
	)
	VALUES (
		id,
		title,
		text);
END;

.....................

END contents_API;


Но даже для такого простого результата xsl-шаблон у меня получился довольно заковыристым:
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
<xsl:stylesheet version = '1.1' xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
<xsl:output method="text" />

<xsl:template match="table">
<xsl:variable name="table_name" select="@name" />
CREATE OR REPLACE PACKAGE <xsl:value-of select="$table_name"/>_API
/*******************************
* API Package for "<xsl:value-of select="@name"/>" table
*******************************/

PROCEDURE ins(
<xsl:for-each select="columns">
   <xsl:for-each select="column">
      <xsl:text>	</xsl:text>
      <xsl:variable name="name_var" select="@name"/>
      <xsl:value-of select="$name_var"/>_i <xsl:value-of select="$table_name"/>.<xsl:value-of select="$name_var"/>%TYPE;<xsl:text>
</xsl:text>
      </xsl:for-each>
   </xsl:for-each>
)
IS
BEGIN
 <xsl:text>	</xsl:text>INSERT INTO <xsl:value-of select="@name"/> (
<xsl:for-each select="columns">
<xsl:for-each select="column">
<xsl:text>	</xsl:text>
<xsl:text>	</xsl:text>
<xsl:variable name="name_var" select="@name"/>
<xsl:value-of select="$name_var"/>
            <xsl:choose>
               <xsl:when test="position() != last()">,<xsl:text>
</xsl:text></xsl:when>
            </xsl:choose>
         </xsl:for-each>
      </xsl:for-each>
<xsl:text>
</xsl:text>
<xsl:text>	</xsl:text>)
<xsl:text>	</xsl:text>VALUES (
<xsl:for-each select="columns">
<xsl:for-each select="column">
<xsl:text>	</xsl:text>
<xsl:text>	</xsl:text>
<xsl:variable name="name_var" select="@name"/>
<xsl:value-of select="$name_var"/>
            <xsl:choose>
               <xsl:when test="position() != last()">,<xsl:text>
</xsl:text></xsl:when>
            </xsl:choose>
         </xsl:for-each>
      </xsl:for-each>
<xsl:text>
</xsl:text>
<xsl:text>	</xsl:text>



<xsl:text>	</xsl:text><xsl:text>	</xsl:text>

<xsl:text>	</xsl:text>);
END;

END <xsl:value-of select="@name"/>_API;
</xsl:template>
</xsl:stylesheet>


Циклы, различные проверки на последнюю строку, в зависимости от которых ставятся переносы строк и т.д.
Дальше будет только хуже.

Подскажите как лучше сделать?

Может адаптировать исходный xml, например так:
Код: xml
1.
2.
3.
4.
5.
6.
7.
   <package name="contents_API">
      <spec>
         <field name="id" type="NUMBER" line_break="no" end_comma="yes" />
         <field name="title" type="VARCHAR2" line_break="no" end_comma="yes" />
         <field name="text" type="CLOB" line_break="yes" end_comma="no" />
      </spec>
   </package>



Т.о. xsl будет попроще, но получается, что в xml-структуру попадают элементы форматирования?
...
Рейтинг: 0 / 0
23.06.2012, 15:28
    #37851475
Antonariy
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
xsl шаблон для кодогенератора
Максим Н Подскажите как лучше сделать?Забить на переносы строк?
Если код генерится, то как правило для немедленного исполнения и отправки в астрал, а не для оценки придирчивыми искусствоведами.
Максим НТ.о. xsl будет попроще, но получается, что в xml-структуру попадают элементы форматирования?У вас на выходе текст, а не xml, о какой xml-структуре идет речь?
...
Рейтинг: 0 / 0
23.06.2012, 16:01
    #37851506
Максим Н
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
xsl шаблон для кодогенератора
AntonariyЗабить на переносы строк?
Если код генерится, то как правило для немедленного исполнения и отправки в астрал, а не для оценки придирчивыми искусствоведами.
В данном случае (да и вообще) офрмление кода очень важно - чтобы быстро разобраться что к чему и быстро внести нужные поправки. Чтобы сгенерированный код соостветсвовал стандартам офрмления остального кода проекта.

AntonariyУ вас на выходе текст, а не xml, о какой xml-структуре идет речь?
Я говорю об исходном xml, где просто описана таблица. Можно добавить информацию о переносах строк, запятых и т.д. туда. Но тогда xml перестанет быть универсальным.
...
Рейтинг: 0 / 0
23.06.2012, 16:24
    #37851527
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
xsl шаблон для кодогенератора
1) В XSL использовать отступы. Будет легче читать
2) Вложенные <xsl:for-each> заменить на один
Код: xml
1.
<xsl:for-each select="columns/column">


3) Все <xsl:for-each> заменить на <xsl:apply-templates>
4) Вот этоМаксим Н
Код: xml
1.
<xsl:text>	</xsl:text>

заменить на
Код: xml
1.
2.
3.
4.
5.
6.
7.
8.
9.
<xsl:template name="ident">
  <xsl:param name="cnt"/>
  <xsl:if test="$cnt &gt; 0">
    <xsl:text>	</xsl:text>
    <xsl:call-template name="ident">
      <xsl:with-param name="cnt" select="$cnt -1"/>
    </xsl:call-template>
  </xsl:if>
</xsl:template>


5) Вот этоМаксим Н
Код: xml
1.
<xsl:value-of select="$name_var"/>_i <xsl:value-of select="$table_name"/>.<xsl:value-of select="$name_var"/>%TYPE;

Заменить на
Код: xml
1.
<xsl:value-of select="concat($name_var, '_i ', $table_name, '.', $name_var, '%TYPE')"/>


6) ЭтоМаксим Н
Код: xml
1.
2.
3.
4.
5.
<xsl:choose>
  <xsl:when test="position() != last()">,<xsl:text>
</xsl:text>
  </xsl:when>
</xsl:choose>

заменить на
Код: xml
1.
2.
3.
<xsl:if test="position() != last()">,<xsl:text>
</xsl:text>
</xsl:when>



Когда все сделаете код сильно упростится. После этого можете выложить его еще раз. Мы его еще подправим
...
Рейтинг: 0 / 0
02.07.2012, 10:53
    #37862518
Dmitry.
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
xsl шаблон для кодогенератора
для перевода каретки можно использовать
Код: xml
1.
<xsl:text>&#10;</xsl:text>
...
Рейтинг: 0 / 0
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / xsl шаблон для кодогенератора / 5 сообщений из 5, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]