Сопоставьте идентификатор элемента в for-each с идентификатором другого элемента - PullRequest
0 голосов
/ 09 февраля 2019

Извините, если мой заголовок не очень ясен: мне трудно придумать правильный способ кратко сформулировать мою проблему.

Вот как выглядит моя XML структура:

<library>
    <books>
        <book writers="007,911">
            <title>Two authors wrote me</title>
            <price>4.00</price>
        </book>
        <book writers="911">
            <title>Only one here</title>
            <price>2.50</price>
        </book>
    </books>
    <authors>
        <author id="007">
            <name>James</name>
        </author>
        <author id="911">
            <name>Police</name>
        </author>
        <author id="666">
            <name>Diablo</name>
        </author>
    </authors>
</library>

Моя цель для каждого author: перечислить своих детей (здесь я только представляю name), но также перечислить все book, где текущийid соответствует хотя бы одному из writers.Если соответствие book не найдено, список book s для этого конкретного author не должен отображаться.Этот список должен быть отсортирован в порядке убывания цены для всех совпадений.

Вот основные XSLT части кода, которые я сделал до сих пор:

<xsl:template match="/"> <!-- I'm skipping all the irrelevant <html> stuff, of course. -->

    <body>
        <ol> 
            <xsl:for-each select="//author">
                <li>
                    <b>ID: </b><xsl:value-of select="@id"/>
                    <ul>
                        <xsl:call-template name="auth_infos"></xsl:call-template>
                        <xsl:call-template name="books_stuff"></xsl:call-template>
                    </ul>
                </li>
            </xsl:for-each>
        </ol>
    </body>

</xsl:template>

<xsl:template name="auth_infos">
    <li><b>Name: </b><xsl:value-of select="name"/></li>
</xsl:template>

<xsl:template name="books_stuff">
    <xsl:if test="//book[//author/@id = @writers]"> <!-- This is supposed to make sure that if the author doesn't have any books listed in the database, then there shouldn't be an empty list of books. Only his name should be presented. -->
        <li><b>Book(s): </b>
            <xsl:for-each select="//book[//author/@id = @writers]">
                <xsl:sort select="price" order="descending"/> <!-- Because I would also like to sort them based on their price. -->
                <li><b>Title: </b><xsl:value-of select="//title"/></li>
            </xsl:for-each>
        </li>
    </xsl:if>
</xsl:template>

Очевидно, у меня проблемы с этим конкретным XPath выражением : "//book[//author/@id = @writers]".Кажется, я не понимаю, как убедиться, что я проверяю совпадение только для идентификатора current author, который повторяется.Кроме того, поскольку book s может иметь несколько writers (от IDREFS до author идентификатора), я не уверен, как применить оператор contains.

Результатом будет что-токак это:

-ID: 007
    -Name: James
    -Book(s):
        -Title: Two authors wrote me
-ID: 911
    -Name: Police
    -Book(s):
        -Title: Two authors wrote me
        -Title: Only one here
-ID: 666
    -Name: Diablo

1 Ответ

0 голосов
/ 09 февраля 2019

Если вы ограничены XSLT 1.0, это будет немного неловко:

XSLT 1.0

<xsl:stylesheet version="1.0"   
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">    
<xsl:output method="html" encoding="utf-8"/>  

<xsl:template match="/library">    
   <body>
        <ol> 
            <xsl:for-each select="authors/author">
                <xsl:variable name="books" select="../../books/book[contains(concat(',', @writers, ','), concat(',', current()/@id, ','))]"/>
                <li>
                    <b>ID: </b>
                    <xsl:value-of select="@id"/>
                    <ul>
                        <li>
                            <b>Name: </b>
                            <xsl:value-of select="name"/>
                        </li>
                        <xsl:if test="$books">
                            <li>
                                <b>Book(s): </b>
                                <ul>
                                    <xsl:for-each select="$books">
                                        <xsl:sort select="price" data-type="number" order="descending"/> 
                                        <li><b>Title: </b><xsl:value-of select="title"/></li>
                                    </xsl:for-each>
                                </ul>
                            </li>
                        </xsl:if>
                    </ul>
                </li>
            </xsl:for-each>
        </ol>
    </body>
</xsl:template>    

</xsl:stylesheet>    

Применительно к вашему примерурезультат s:

<body><ol>
<li>
<b>ID: </b>007<ul>
<li>
<b>Name: </b>James</li>
<li>
<b>Book(s): </b><ul><li>
<b>Title: </b>Two authors wrote me</li></ul>
</li>
</ul>
</li>
<li>
<b>ID: </b>911<ul>
<li>
<b>Name: </b>Police</li>
<li>
<b>Book(s): </b><ul>
<li>
<b>Title: </b>Two authors wrote me</li>
<li>
<b>Title: </b>Only one here</li>
</ul>
</li>
</ul>
</li>
<li>
<b>ID: </b>666<ul><li>
<b>Name: </b>Diablo</li></ul>
</li>
</ol></body>

Отображается как:

enter image description here

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