Модераторы: diadiavova
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> XSLT 1.0: корректно добавить атрибуты, Ошибка при добавлении атрибутов 
:(
    Опции темы
av84
Дата 20.1.2015, 15:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 20.1.2015

Репутация: нет
Всего: нет



   Привет всем.

 Прошу помочь разобраться с XSLT.

Стоит задача выбрать определённый набор узлов из HTML-документа и преобразовать его - обернуть каждый узел в div и span. 
К примеру:
Код

<div>
        <h1 color="red" font-weight="bold">head 1</h1>
        <h2 color="blue" font-style="italic">head 2</h2>
        <p border-style="double">Paragraph</p>
        <div class="div">
            <p class="subp">Sub paragraph</p>
            <div class="subdiv">
                <span>span</span>
                <p class="subsubp">Sub sub paragraph<span>Sub sub span</span></p>
            </div>
        </div>
</div>


У узлов будет множество атрибутов. В этом вся загвоздка.

Пишу xsl-документ:

Код

    <xsl:template match="/">
        <sheet>
            <xsl:apply-templates select="//h1 | //h2 | //h5 | //p | //tr />
        </sheet> 
    </xsl:template>
      

            
    <xsl:template match="*"> 
        <xsl:choose>
            
            <xsl:when test="name() = 'tr'">
                <xsl:element name="div">       
                    <xsl:apply-templates select="./td | ./th"/>   
                </xsl:element>                   
            </xsl:when>
                                
            <xsl:otherwise>
                <xsl:element name="div">          
                    <xsl:element name="span"> 
                        <xsl:value-of select="."/>
                    </xsl:element>
                </xsl:element>                  
            </xsl:otherwise>
                        
        </xsl:choose> 

    </xsl:template>      
    
    
    
    <xsl:template match="tr/td"> 
        <xsl:element name="span">    
            <xsl:value-of select="."/>
        </xsl:element>        
    </xsl:template>
    
    <xsl:template match="tr/th"> 
        <xsl:element name="span">    
            <xsl:value-of select="."/>
        </xsl:element>        
    </xsl:template>    



Всё хорошо "оборачивается". Но как только я пытаюсь добавить или скопировать атрибуты, сразу же лезут ошибки. 
К примеру, если пишу

Код

<xsl:template match="@color">
 <xsl:copy>
  <xsl:apply-templates select="@color"/>
 </xsl:copy>
</xsl:template>     


выдаётся 
"XSLTProcessor::importStylesheet(): element template only allowed as child of stylesheet"
и
"XSLTProcessor::importStylesheet(): XSLT-apply-templates: could not compile select expression '@color*'"

Идеальный вариант был бы через for-each прогнать все атрибуты и скопировать/создать их, но ничего не выходит.

Стоит ли что-то существенно переделать, избавившись от цикла, или дополнить текущий функционал?
Буду очень признателен за помощь.

Это сообщение отредактировал(а) av84 - 21.1.2015, 08:12
PM MAIL   Вверх
diadiavova
Дата 20.1.2015, 18:00 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 22
Всего: 142



Цитата(av84 @  20.1.2015,  15:57 Найти цитируемый пост)
@color*"

Насколько я понимаю, таким образом ты хотел отобрать все атрибуты, начинающиеся с color? Такое не поддерживается, звездочкой можно заменить имя элемента или атрибута полностью, но применить ее к части имени не получится. Надо сделать как-то так примерно
Код

@*[starts-with(name(), 'color')]


Или в темплейте просто указать @color, а внутри уже в ифе копировать только те атрибуты, которые соответствуют этому условию.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
av84
Дата 21.1.2015, 07:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 20.1.2015

Репутация: нет
Всего: нет



diadiavova

спасибо, но, к сожалению, не всё так просто (или наоборот проще некуда?). 

Мне нужно пройтись по всем узлам документа, выбрать определённый набор узлов, и заменить:
- p, h1-h6 на div>span с таким же значением узлов, а атрибуты скопировать в span;
- tr на div;
- td на span.

То есть, к примеру, из документа:

Код

<div>
        <h1 color="red" font-weight="bold">head 1</h1>
        <h2 color="blue" font-style="italic">head 2</h2>
        <p border-style="double">Paragraph</p>
        <div class="div">
            <p class="subp">Sub paragraph</p>
            <div class="subdiv">
                <span>span</span>
                <p class="subsubp">Sub sub paragraph<span>Sub sub span</span></p>
            </div>
        </div>
</div>
<table>
  <thead>
      <tr>
          <td>a11</td>
          <td>b22</td>
      </tr>
      <tr>
          <td>c33</td>
          <td>d44</td>
      </tr>      
  </thead>
</table>  


нужно получить 

Код

        <div><span color="red" font-weight="bold">head 1</span></div>
        <div><span color="blue" font-style="italic">head 2</span></div>
        <div><span border-style="double">Paragraph</span></div>
        <div><span class="subp">Sub paragraph</span></div>
        <div><span class="subsubp">Sub sub paragraph</span></div>

      <div>
          <span>a11</span>
          <span>b22</span>
      </div>
      <div>
          <span>c33</span>
          <span>d44</span>
      </div> 
     
  
Узлы заменяются, а атрибуты не выходит скопировать.

Это сообщение отредактировал(а) av84 - 21.1.2015, 08:13
PM MAIL   Вверх
diadiavova
Дата 21.1.2015, 20:49 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 22
Всего: 142



Цитата(av84 @  21.1.2015,  07:38 Найти цитируемый пост)
спасибо, но, к сожалению, не всё так просто (или наоборот проще некуда?). 

Я посмотрел в первую очередь на ошибки, которые выдал компилятор. Исходя из первого сообщения следует, что ты воткнул темплейт не туда куда надо, он должен быть дочерним по отношению к корневому элементу стайлшит и никакие другие места для него не допускаются. Второе сообщение касалось как раз-таки селектора @color*, собственно о нем я и написал.
Цитата(av84 @  21.1.2015,  07:38 Найти цитируемый пост)
Узлы заменяются, а атрибуты не выходит скопировать.

Ну как вариант можно использовать форич в сочетании с копиоф. По тому, что ты описал, получилось следующее
Код

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output method="xml" indent="yes"/>
  <xsl:template match="*">
    <xsl:apply-templates select="*"/>
  </xsl:template>
  <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates/>
    </xsl:copy>
  </xsl:template>
 
  <xsl:template match="p|h1|h2|h3|h4|h5|h6">
    <div>
      <span>
        <xsl:for-each select="@*">
          <xsl:copy-of select="."/>
        </xsl:for-each>
        <xsl:apply-templates/>
        </span>
    </div>  
  </xsl:template>

  <xsl:template match="tr">
    <div>
      <xsl:apply-templates/>
    </div>
  </xsl:template>

  <xsl:template match="td">
    <span>
      <xsl:apply-templates/>
    </span>
  </xsl:template>

  
</xsl:stylesheet>




--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
av84
Дата 22.1.2015, 08:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 20.1.2015

Репутация: нет
Всего: нет



diadiavova,

спасибо большое. Это то, что нужно. 

P.S. прошу прощения, но по ошибке нажал "report" над вашим сообщением. 
PM MAIL   Вверх
diadiavova
Дата 23.1.2015, 00:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 22
Всего: 142



Цитата(av84 @  22.1.2015,  08:11 Найти цитируемый пост)
 по ошибке нажал "report" над вашим сообщением

Эт ничаво smile 


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
av84
Дата 9.2.2015, 15:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 20.1.2015

Репутация: нет
Всего: нет



diadiavova,

можно ещё спросить у вас помощи? 
Расширяю функционал преобразования, и не получается одна вещь.

Стоит задача преобразовать, к примера, такой участок документа:

Код

<table>
<thead>
<tr>
<th class="corner ">ID</th>
<th class="corner ">ID родителя</th>
<th class="corner ">S_NAME</th>
<th class="corner ">Уровень</th>
</tr>
</thead>
<tbody>
<tr class="">
<th id="l16_ID_REPORT">16</th>
<th id="l16_IDP"><div class="s_text">100001</div></th>
<th id="l16_IDN"><div id="head_1">HEAD #1<p>TEXT #1<span class="level2">Отчет об актуальном состоянии</span></p></div></th>
<th id="l16_LVL">2</th>
</tr>
<tr class="">
<th id="l84_ID_REPORT">84</th>
<th id="l84_IDP"><div class="s_text">100002</div></th>
<th id="l84_IDN"><div><span id="head_2">HEAD #2</span><span class="level2">Отчет об актуальном состоянии</span></div></th>
<th id="l84_LVL">2</th>
</tr>
</tbody>
</table>


вот в такой:

Код

<block>
<string class="corner " sharedString="0">ID</string>
<string class="corner " sharedString="0">ID родителя</string>
<string class="corner " sharedString="0">S_NAME</string>
<string class="corner " sharedString="0">Уровень</string>
</block>
<block class="">
<string id="l7_ID_REPORT" sharedString="0">7</string>
<string class="s_text" sharedString="0">100001</string>
<string sharedString="3"><sharedString id="head_1">HEAD #1</sharedString><sharedString>TEXT #1</sharedString><sharedString class="level2">Отчет об актуальном состоянии</sharedString></string>
<string id="l7_LVL" sharedString="0">2</string>
</block>
<block class="">
<string id="l84_ID_REPORT" sharedString="0">84</string>
<string class="s_text" sharedString="0">100001</string>
<string sharedString="2"><sharedString id="head_2">HEAD #2</sharedString><sharedString class="level2">Отчет об актуальном состоянии</sharedString></string>
<string id="l84_LVL" sharedString="0">2</string>
</block>


То есть основная сложность - обернуть все текстовые узлы, входящие в td или th в sharedString, сохранив при этом атрибуты родительского узла.

Что я сделал:

Код

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml" indent="yes" />
    
    
    <xsl:template match="*">
        <xsl:apply-templates select="*" />
    </xsl:template>
  
    <xsl:template match="/*">
        <xsl:copy>
            <xsl:apply-templates />
        </xsl:copy>  
    </xsl:template>
    
    
    <xsl:template match="tr">
        <block>           
            <xsl:apply-templates />
        </block>
    </xsl:template>    
    
    <xsl:template match="td | th">
        <string>

            <xsl:attribute name="sharedString">
                <xsl:value-of select="count(.//text())" />
            </xsl:attribute>
            
            <xsl:choose>
                
            <xsl:when test="count(.//text()) > 1">
                <xsl:for-each select=".//text()">
                    <sharedString>
                        <xsl:for-each select="./parent::*">
                        </xsl:for-each>                           
                        <xsl:copy-of select="." />
                    </sharedString>
                </xsl:for-each>                     
                <xsl:apply-templates />  
            </xsl:when>     
            
            <xsl:otherwise>
                <xsl:for-each select="@*">
                    <xsl:copy-of select="." />
                </xsl:for-each>                
            <xsl:apply-templates />                
            </xsl:otherwise>                      
                
            </xsl:choose>

        </string>        
    
    </xsl:template>        
  
</xsl:stylesheet>



У меня получается следующее:

Код

<block>
<string class="corner " sharedString="0">ID</string>
<string class="corner " sharedString="0">ID родителя</string>
<string class="corner " sharedString="0">S_NAME</string>
<string class="corner " sharedString="0">Уровень</string>
</block>
<block class="">
<string id="l7_ID_REPORT" sharedString="0">7</string>
<string class="s_text" sharedString="0">100001</string>
<string sharedString="3"><sharedString>HEAD #1</sharedString><sharedString>TEXT #1</sharedString><sharedString>Отчет об актуальном состоянии</sharedString></string>
<string id="l7_LVL" sharedString="0">2</string>
</block>
<block class="">
<string id="l84_ID_REPORT" sharedString="0">84</string>
<string class="s_text" sharedString="0">100001</string>
<string sharedString="2"><sharedString>HEAD #2</sharedString><sharedString>Отчет об актуальном состоянии</sharedString></string>
<string id="l84_LVL" sharedString="0">2</string>
</block>


То есть не выходит скопировать атрибуты родителя текстового узла для sharedString.

Буду очень вам признателен, если подскажите, как можно это сделать или где и что посмотреть для этого.
PM MAIL   Вверх
diadiavova
Дата 9.2.2015, 16:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5820
Регистрация: 14.8.2008
Где: В Коньфпольте

Репутация: 22
Всего: 142



Бегло просмотрел и вот что смутило
Цитата(av84 @  9.2.2015,  15:44 Найти цитируемый пост)
                        <xsl:for-each select="./parent::*">
                        </xsl:for-each>                           
                        <xsl:copy-of select="." />

Пустой форич и копируешь неизвестно что и неизвестно куда, а в следующей ветке вроде копируешь атрибут, но при этом не  создаешь элемент. Куда ты его копируешь? Я не вникал, может вечером посмотрю, если ты не решишь к тому времени, но сделать надо примерно так: обходи не текстовые узлы, а элементы, содержащие текстовые узлы примерно такие //td//*[text()], для каждого такого элемента создавай sharedString и копируй в него сначала атрибуты, потом -  текст.


--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
av84
Дата 10.2.2015, 11:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 20.1.2015

Репутация: нет
Всего: нет



Цитата

 а элементы, содержащие текстовые узлы примерно такие //td//*[text()]


Дело в том, что если так выбирать, то копируется всё один-в-один, не оборачивая текст в sharedString.

Я немного доработал представленный мной же выше способ, и всё получилось как надо:

Код

    <xsl:template match="td | th" priority="2">
        <string>
            
            <xsl:attribute name="sharedString">
                <xsl:value-of select="count(.//*[text()])" />
            </xsl:attribute>
            
            <xsl:choose>
                
                <xsl:when test="count(.//*[text()]) > 1">
                    <xsl:for-each select=".//text()">
                        <sharedString>
                            <xsl:for-each select="./parent::*">
                                <xsl:copy-of select="@*" /> 
                            </xsl:for-each>                
                            <xsl:copy-of select="." />  
                        </sharedString>
                    </xsl:for-each>                     
                    <xsl:apply-templates />  
                </xsl:when>     
                
                <xsl:when test="count(.//*[text()]) = 1">
                    <xsl:for-each select=".//text()">
                            <xsl:for-each select="./parent::*">
                                <xsl:copy-of select="@*" /> 
                            </xsl:for-each>                
                            <xsl:copy-of select="." />  
                    </xsl:for-each>                     
                    <xsl:apply-templates />  
                </xsl:when>                  
            
                <xsl:otherwise>
                <xsl:for-each select="@*">
                    <xsl:copy-of select="." />
                </xsl:for-each>
                <xsl:apply-templates />            
                </xsl:otherwise>                      
                
            </xsl:choose>

        </string>        
    
    </xsl:template>  


В любом случае спасибо. Вы меня натолкнули на мысль для другого преобразования =)
PM MAIL   Вверх
av84
Дата 13.4.2015, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 20.1.2015

Репутация: нет
Всего: нет



Добрый день. 
У меня опять загвоздка. Начинаю понемногу разбираться в XSLT, но всё равно не всё выходит. Очень надеюсь на подсказку. 

Посмотрите, пожалуйста.
Имеется преобразованная таблица. К примеру:

Код

<?xml version="1.0"?>
<html>
  <block><string sharedString="0">first 1</string>
      <string sharedString="0">first 2</string>     
      <string sharedString="0">first 3</string>     
    </block>
  <block><string sharedString="0" rowspan="3">s11</string>
     <string sharedString="0">s22</string>
     <string sharedString="0" rowspan="3">s55</string> 
    </block>
  <block><string sharedString="0">s33</string>
    </block>
  <block><string sharedString="0">s44</string>
    </block>
</html>



Преобразовываю я её, к слову, вот так:

Код

<?xml version="1.0" encoding="utf-8"?>  

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    
    <xsl:template match="/">
        <sheet>        
          <xsl:apply-templates select="//block" />
        </sheet> 
    </xsl:template>
    
 
    <xsl:template match="block">   
        <row> 
                         
            <xsl:attribute name="r">
                <xsl:value-of select="position()" />
            </xsl:attribute>
            <xsl:if test="@src">
                <xsl:attribute name="src">
                    <xsl:value-of select="@src" />
                </xsl:attribute>
            </xsl:if>

            <xsl:apply-templates select="string" />
     
        </row>
    </xsl:template>

  
    <xsl:template match="string"> 
        <c>       
            
            <xsl:attribute name="col_position">
                <xsl:value-of select="position()" />
            </xsl:attribute>            
              
            <xsl:if test="count(./sharedString) > 1">
                
            </xsl:if>            
                       
            <xsl:for-each select="@*">
                <xsl:copy-of select="." />
            </xsl:for-each>                                                                       
        
            <xsl:value-of select="normalize-space(text())"/>

        </c>

        <xsl:if test="@colspan">
            <xsl:call-template name="for">
                <xsl:with-param name="n" select="./@colspan"/>
            </xsl:call-template>
        </xsl:if>    
        
    </xsl:template>
    
    
    <xsl:template name="for">
        
        <xsl:param name="i" select="0"/>
        <xsl:param name="n"/>
        
        <xsl:if test="$i &lt; $n - 1">
            <c nottransform="1" />
            
            <xsl:call-template name="for">
                <xsl:with-param name="i" select="$i + 1"/>
                <xsl:with-param name="n" select="$n"/>
            </xsl:call-template>
            
        </xsl:if>
        
    </xsl:template>    


</xsl:stylesheet>



И получается:

Код

<?xml version="1.0"?>
<sheet>
  <row r="1">
    <c col_position="1" sharedString="0">first 1</c>
    <c col_position="2" sharedString="0">first 2</c>
    <c col_position="3" sharedString="0">first 3</c>
  </row>
  <row r="2">
    <c col_position="1" sharedString="0" rowspan="3">s11</c>
    <c col_position="2" sharedString="0">s22</c>
    <c col_position="3" sharedString="0" rowspan="3">s55</c>
  </row>
  <row r="3">
    <c col_position="1" sharedString="0">s33</c>
  </row>
  <row r="4">
    <c col_position="1" sharedString="0">s44</c>
  </row>
</sheet>



Но вопрос следующий: возможно ли получить такое:

Код

<?xml version="1.0"?>
<sheet>
  <row r="1">
    <c col_position="1" sharedString="0">first 1</c>
    <c col_position="2" sharedString="0">first 2</c>
    <c col_position="3" sharedString="0">first 3</c>
  </row>
  <row r="2">
    <c col_position="1" sharedString="0" rowspan="3">s11</c>
    <c col_position="2" sharedString="0">s22</c>
    <c col_position="3" sharedString="0" rowspan="3">s55</c>
  </row>
  <row r="3">
    <c col_position="1" sharedString="0" nottransform="1" />
    <c col_position="2" sharedString="0">s33</c>
    <c col_position="3" sharedString="0" nottransform="1" />
  </row>
  <row r="4">
    <c col_position="1" sharedString="0" nottransform="1" />
    <c col_position="2" sharedString="0">s44</c>
    <c col_position="3" sharedString="0" nottransform="1" />
  </row>
</sheet>


?

То есть добавить на места "ячеек", на которые распространяется "действие" rowspan'ов, пустые узлы с атрибутом nottransform.

Получается, высчитываем по значению атрибута на какое кол-во элементов row распространяется "действие" rowspan'а, берём значение позиции элемента c и каким-то образом добавляем и сортируем? Или как?
Как это лучше сделать? Возможно ли вообще подобное? 

Буду очень благодарен за помощь или подсказку.



PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "XML/XSLT"
diadiavova

Прежде чем опубликовать вопрос, попробуйте воспользоваться поиском - возможно тема уже поднималась.

Также рекомендуем Вам зайти в раздел FAQ ,раздел дополняется и, возможно, там вы увидите готовое решение.

Для ответов на часто задаваемые вопросы существует FAQ раздела. Новости можно публиковать в разделе новостей. Для статей так же есть специальный раздел

Желаем удачи в Вашем деле!


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, diadiavova.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | XML, XSL | Следующая тема »


 




[ Время генерации скрипта: 0.1639 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.