powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / XML, XSL, XPath, XQuery [игнор отключен] [закрыт для гостей] / xsl шаблон для кодогенератора
5 сообщений из 5, страница 1 из 1
xsl шаблон для кодогенератора
    #37851461
Максим Н
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Делаю небольшой 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
xsl шаблон для кодогенератора
    #37851475
Фотография Antonariy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Максим Н Подскажите как лучше сделать?Забить на переносы строк?
Если код генерится, то как правило для немедленного исполнения и отправки в астрал, а не для оценки придирчивыми искусствоведами.
Максим НТ.о. xsl будет попроще, но получается, что в xml-структуру попадают элементы форматирования?У вас на выходе текст, а не xml, о какой xml-структуре идет речь?
...
Рейтинг: 0 / 0
xsl шаблон для кодогенератора
    #37851506
Максим Н
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AntonariyЗабить на переносы строк?
Если код генерится, то как правило для немедленного исполнения и отправки в астрал, а не для оценки придирчивыми искусствоведами.
В данном случае (да и вообще) офрмление кода очень важно - чтобы быстро разобраться что к чему и быстро внести нужные поправки. Чтобы сгенерированный код соостветсвовал стандартам офрмления остального кода проекта.

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


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