Помогите распарсить XML при помощи XSLT

MadBump

Новичок
Помогите распарсить XML при помощи XSLT

Надо из
PHP:
<table>
    <row>
        <col colspan="3">
            Раздел 1
        </col>
    </row>

    <row>
        <col>Сайт 1</col>
        <col>URL 1</col>
        <col>описание 1</col>
    </row>

    
    <row>
        <col>Сайт 2</col>
        <col>URL 2</col>
        <col>описание 2</col>
    </row>

    
    <row>
        <col colspan="3">
            Раздел 2
        </col>
    </row>

    
    <row>
        <col>Сайт 3</col>
        <col>URL 3</col>
        <col>описание 3</col>
    </row>
    
    <row>
        <col>Сайт 4</col>
        <col>URL 4</col>
        <col>описание 4</col>
    </row>
</table>
получить это

PHP:
<sites>
    <site>
        <cat>Раздел 1</cat>
        <name>Сайт 1</name>
        <url>URL 1</url>
        <descr>описание 1</descr>
    </site>
    
    <site>
        <cat>Раздел 1</cat>
        <name>Сайт 2</name>
        <url>URL 2</url>
        <descr>описание 2</descr>
    </site>

    
    <site>
        <cat>Раздел 2</cat>
        <name>Сайт 3</name>
        <url>URL 3</url>
        <descr>описание 3</descr>
    </site>

    
    <site>
        <cat>Раздел 2</cat>
        <name>Сайт 4</name>
        <url>URL 4</url>
        <descr>описание 4</descr>
    </site>

</sites>

Я все сам сделал, но есть одна проблема: как получить название раздела и его использовать в последующем, т.к. xsl:variable нельзя переопределять повторно.

Заранее спасибо!
 

MadBump

Новичок
xsl:key не совсем подходит, я не смог придумать как его можно было бы использовать

а можно ли через xpath получить значение из <col colspan="3"> первого вышестоящего узла относительно текущего обрабатываемого <row>?
 

Alexandre

PHPПенсионер
а можно ли через xpath получить значение из <col colspan="3">
xpath здесь ни как не прикрутишь

xsl:key не совсем подходит, я не смог придумать как его можно было бы использовать
анализируй....
http://xpoint.ru/forums/internet/XML/thread/38992.xhtml
http://xpoint.ru/forums/internet/XML/thread/32646.xhtml
http://xpoint.ru/forums/internet/XML/thread/26770.xhtml
 

MadBump

Новичок
это я все видел уже, только не могу придумать как это использовать
 

Alexandre

PHPПенсионер
Проштудируй ман еще разик
denver - умник такой, :D
ну и что это даст?:confused:

Существенная помощь для анализа: http://xmlhack.ru/books/xslt/ch_11.html
Да, в этом случае надо использовать метод группировки Стивена Мюнха...
olpa - еще раз убеждаюсь, хороший у тебя ресурс.
 

denver

?>Скриптер
Alexandre
ну и что это даст?
Найдешь для себя много нового :)

Например про существование таких осей как preceding-sibling и following-sibling дающих возможность выбирать в горизонтальной плоскости в отличие от ancestor, descendant.
 

Alexandre

PHPПенсионер
Найдешь для себя много нового
denver уже нашел ... лет эдак пять назад...
ты не вчитался в вопрос, повторю...
что это даст для этого конкретноко случая, код в студию, плииииз
 

MadBump

Новичок
А даст очень многое, просто каждый раз будем получать эту самую строчку сверху, которая так портит нам жизнь
 

Alexandre

PHPПенсионер
MadBump сказал А, говори Б - пример...

В данном случае это ничего не даст:
как получить название раздела и его использовать в последующем
как ты будешь получать название раздела в последующем? это не будет привязано к текущему контексту...
и вариант
Например про существование таких осей как preceding-sibling и following-sibling дающих возможность выбирать в горизонтальной плоскости в отличие от ancestor, descendant.
в этом случае не подходит.

как варант - было предложено использовать группировку стива Мюнча.
 

MadBump

Новичок
2 denver:

Акак сделать, чтобы он брал первую такую строку над текущей,
а то по

preceding-sibling::row/col[@colspan=3]

оно берет самую верхнюю строку?
 

denver

?>Скриптер
MadBump
Выложи код XSL, посмотрим.

Быть может:
preceding-sibling::row/col[@colspan=3][position()=last()]
 

MadBump

Новичок
Автор оригинала: denver
MadBump
Выложи код XSL, посмотрим.

Быть может:
preceding-sibling::row/col[@colspan=3][position()=last()]
не помогло, все равно первую строку берет

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

<xsl:output method="xml" encoding="utf8" indent="no"/>


    <xsl:template match="/">
        <sites>
                <xsl:for-each select=".//row">

                    

                        <xsl:variable name="catname1"><xsl:value-of select="col[3]"/></xsl:variable>
                        <xsl:variable name="catname2"><xsl:value-of select="col[2]"/></xsl:variable>
                        
                                
                        <xsl:choose>
                            <xsl:when test="(string-length($catname1)=0) and (string-length($catname2)=0)">
                        
                            </xsl:when>

                            <xsl:otherwise>
                                <site>
                                
                                    <cat>
                                        <xsl:value-of select="preceding-sibling::row/col[@colspan=3][position()=last()]"/>
                                    </cat>
                                                
                                    <xsl:for-each select=".//col">
                                        <xsl:choose>

                                            <xsl:when test="position()=1">
                                                <name>
                                                    <xsl:value-of select="text()"/>
                                                </name>

                                            </xsl:when>

                                            <xsl:when test="position()=2">
                                                <url>
                                                    <xsl:value-of select="text()"/>
                                                </url>
                                            </xsl:when>

                                            <xsl:when test="position()=3">
                                                <descr>
                                                    <xsl:value-of select="text()"/>
                                                </descr>
                                            </xsl:when>


                                        </xsl:choose>
                                    </xsl:for-each>
                                </site>
                            
                            </xsl:otherwise>
                        </xsl:choose>
                        

                </xsl:for-each>
        </sites>
    </xsl:template>


</xsl:stylesheet>
 

denver

?>Скриптер
Странная штука, вот такая конструкция:

PHP:
<xsl:copy-of select="preceding-sibling::row/col[@colspan=3][position()=last()]"/>
возвращает почему-то *все* предыдущие, т.е. плюет на position()=last() :-/

Хотя вот такое вот работает верно:

PHP:
<xsl:for-each select="preceding-sibling::row/col[@colspan=3]">
	<xsl:if test="position()=last()">
		<xsl:value-of select="."/> 
	</xsl:if>
</xsl:for-each>
Наверное я тоже что-то не понимаю :(
 

Alexandre

PHPПенсионер
MadBump Несколько советов.
Шаблон громоздкий и невоспринимаем,
надо, как и в ООП,
бить на маленькие и восприимчивые функции
для этого использовать <xsl:template match =...> или <xsl:call-template

Когда научишься использовать <xsl:template /> то группировка Мюнча покажется "детским садом"....
и повторное использование будет проще
 

Alexandre

PHPПенсионер
MadBump надо его бить на более мелкие,
как советует Фаулер, если ваша функция (метод) более 15 операторов, то задумайтесь о Рефакторинге.
 
Сверху