Как применить шаблон XSLT к копии узла, используя переменные условия (извлеченные из предыдущего узла XML) - PullRequest
3 голосов
/ 18 сентября 2011

Я новичок в XSLT-преобразованиях. Я пишу некоторые преобразования для рефакторинга кода, выраженного в srcML, и я столкнулся с проблемой. Ввод XML, с которым я работаю, выглядит следующим образом:

....
<function><type><name>void</name></type> <name>DrawHorizontal</name>
<parameter_list>(
    <param><decl><type><name>t_paper</name></type> <name>p</name></decl></param>,
    <param><decl><type><name>int</name></type> <name>x</name></decl></param>,
    <param><decl><type><name>int</name></type> <name>y</name></decl></param>)
 </parameter_list>
   <block>{.....
     <expr_stmt><expr>
       <name>
         <name>p</name>
         <index>[<expr><name>x</name></expr>]</index>
         <index>[<expr><name>y</name></expr>]</index>
       </name>.
       <name>hor</name>
       <operator>=</operator> 1
     </expr>;</expr_stmt>
  ...
  }</block>
</function>

Что я хочу сделать для каждой функциональной секции:

1) Определить имя параметров определенного типа (например, p типа t_paper)

2) Изменить выражение выражения, в котором находятся параметры, определенные на предыдущем шаге ()

Вывод должен выглядеть так:

.....
<function><type><name>void</name></type> <name>DrawHorizontal</name>
<parameter_list>(
    <param><decl><type><name>t_paper</name></type> <name>p</name></decl></param>,
    <param><decl><type><name>int</name></type> <name>x</name></decl></param>,
    <param><decl><type><name>int</name></type> <name>y</name></decl></param>)
 </parameter_list>
   <block>{.....
     <expr_stmt><expr>
       <name>p</name>.
       <name>
         <name>data</name>
         <index>[<expr><name>x</name></expr>]</index>
         <index>[<expr><name>y</name></expr>]</index>
       </name>.
       <name>hor</name>
       <operator>=</operator> 1
     </expr>;</expr_stmt>
  ...
  }</block>
</function>

Таким образом, мне нужно преобразовывать узлы expr_stmt только там, где находятся параметры определенного типа (t_paper в примере). Остальная часть файла должна быть скопирована как есть.

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

Некоторый НЕ работающий код выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="node() | @*">
   <xsl:copy>
      <xsl:apply-templates select="node() | @*" />
   </xsl:copy>
</xsl:template>

<xsl:template match="//function">
<xsl:choose>
       <xsl:when test="parameter_list/param/decl/type/name='t_paper'">
    <xsl:copy>
     <xsl:call-template name="transform-function" select="node()">
      <xsl:with-param name="appearance" select="parameter_list/param/decl/name" />
     </xsl:call-template>
        </xsl:copy> 
       </xsl:when>
       <xsl:otherwise>
         <function><xsl:apply-templates select="node()"/></function>
   </xsl:otherwise>
</xsl:choose>
 </xsl:template>

 <xsl:template name="transform-function">
<xsl:param name="appearance" />
<xsl:if test="//expr_stmt/expr/name/name=$appearance">
    substitution here
</xsl:if>
 </xsl:template>
</xsl:stylesheet>

Я был бы очень признателен, если бы кто-нибудь дал мне подсказку.

Пожалуйста, дайте мне знать, если вам нужно больше подробностей, так как это мой первый вопрос в SO.

Приветствия

D.

Ответы [ 2 ]

1 голос
/ 18 сентября 2011

Это простое преобразование (без явных условий вообще):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 <xsl:strip-space elements="*"/>

 <xsl:key name="kParamByNameType" match="param"
  use="concat(decl/name, '+', decl/type/name)"/>

 <xsl:template match="node()|@*">
     <xsl:copy>
       <xsl:apply-templates select="node()|@*"/>
     </xsl:copy>
 </xsl:template>

 <xsl:template match=
   "expr/name
         [key('kParamByNameType',
              concat(name, '+', 't_paper')
              )
         ]">
  <xsl:copy-of select="name"/>
  <name>
    <name>data</name>
    <xsl:apply-templates select="name/following-sibling::node()"/>
  </name>
 </xsl:template>
</xsl:stylesheet>

при применении к предоставленному документу XML :

<function>
    <type>
        <name>void</name>
    </type>
    <name>DrawHorizontal</name>
    <parameter_list>(     
        <param>
           <decl>
                    <type>
                        <name>t_paper</name>
                    </type>
                    <name>p</name>
       </decl>
        </param>,     
        <param>
            <decl>
                <type>
                    <name>int</name>
                </type>
                <name>x</name>
            </decl>
        </param>,     
        <param>
            <decl>
                <type>
                    <name>int</name>
                </type>
                <name>y</name>
            </decl>
        </param>)  
    </parameter_list>
    <block>{.....      
        <expr_stmt>
            <expr>
                <name>
                    <name>p</name>
                    <index>[
                        <expr>
                            <name>x</name>
                        </expr>]
                    </index>
                    <index>[
                        <expr>
                            <name>y</name>
                        </expr>]
                    </index></name>.        
                <name>hor</name>
                <operator>=</operator> 1      
            </expr>;
        </expr_stmt>   ...   }
    </block>
</function>

дает желаемый результат :

<function>
   <type>
      <name>void</name>
   </type>
   <name>DrawHorizontal</name>
   <parameter_list>(     
        <param>
         <decl>
            <type>
               <name>t_paper</name>
            </type>
            <name>p</name>
         </decl>
      </param>,     
        <param>
         <decl>
            <type>
               <name>int</name>
            </type>
            <name>x</name>
         </decl>
      </param>,     
        <param>
         <decl>
            <type>
               <name>int</name>
            </type>
            <name>y</name>
         </decl>
      </param>)  
    </parameter_list>
   <block>{.....      
        <expr_stmt>
         <expr>
            <name>p</name>
            <name>
               <name>data</name>
               <index>[
                        <expr>
                     <name>x</name>
                  </expr>]
                    </index>
               <index>[
                        <expr>
                     <name>y</name>
                  </expr>]
                    </index>
            </name>.        
                <name>hor</name>
            <operator>=</operator> 1      
            </expr>;
        </expr_stmt>   ...   }
    </block>
</function>

Пояснение :

  1. Переопределение правило идентификации только для параметров запрошенного типа.

  2. Использование клавиши для удобного определения отображениямежду объявлением параметра и его (имя, тип)

0 голосов
/ 18 сентября 2011

Это ответ функции xsl: key element / key ()

Мне пришлось отступить от вашего двухэтапного решения, чтобы найти работоспособный ответ.Я не знаю, откуда вы берете свое выражение выражения, но я полагаю, что это что-то из C # /. NET.

В любом случае я вижу, что то, что вы делаете, это оборачивает тип так, чтобывыражения меняются с:

p[x][y] to p.data[x][y]

Если это так, вместо применения разных представлений ко всей функции, я выбрал совпадение шаблонов для компонентов выражения.Затем, по условию для каждого имени параметра, я ищу тип, чтобы увидеть, является ли он тем, который вы ищете.Дополнительные операторы «когда» могут быть добавлены для каждого типа, который вы хотите перехватить:

<xsl:template match="node() | @*">
   <xsl:copy>
      <xsl:apply-templates select="node() | @*"/>
   </xsl:copy>
</xsl:template>

<!--  key('parambyname','p')/type/name eq 't_paper' -->
<xsl:key name="parambyname" match="parameter_list/param/decl" use="name"/>

<xsl:template match="//expr_stmt/expr//name">
   <xsl:choose>
      <xsl:when test="key('parambyname',text())/type/name eq 't_paper'">
       <xsl:copy>
                 <xsl:apply-templates select="./text()" />
       </xsl:copy>
       <xsl:text>.</xsl:text>
       <name>data</name>
       <xsl:apply-templates select="!text()"/>
      </xsl:when>
      <xsl:otherwise>
       <xsl:copy>
          <xsl:apply-templates select="node() | @*"/>
       </xsl:copy>
      </xsl:otherwise>
   </xsl:choose>
</xsl:template>

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