Re: [xsl] Seek XPath 2.0 expression for this: Are there any book titles with more than one binding?

Subject: Re: [xsl] Seek XPath 2.0 expression for this: Are there any book titles with more than one binding?
From: "Dimitre Novatchev dnovatchev@xxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Sat, 4 May 2019 06:31:29 -0000
Or even this:

/*/BookTitle/Book
                    [index-of(/*/BookTitle/Book[1]/concat(Author,
'|',Title),
                                   concat(Author, '|', Title)
                                  )[2]
                                        > 0
                     ][1]"/>

which is more readable as:

/*/BookTitle/Book[index-of($vallAuthorTitle, concat(Author, '|', Title))[2]
> 0][1]

if we substitute $vallAuthorTitle for:

                        /*/BookTitle/Book[1]/concat(Author, '|',Title)

Certainly, if Xpath 3 were allowed, then one could use a "let" expression
for this substitution -- and then other, better solutions would be possible
using the simple mapping operator "!"  and/or maps.

Something more about the technique used in these expressions can be found
here:
https://dnovatchev.wordpress.com/2008/11/16/xpath-2-0-gems-find-all-duplicate-values-in-a-sequence-part-2/



Cheers,
Dimitre

On Thu, May 2, 2019 at 9:20 AM Dimitre Novatchev <dnovatchev@xxxxxxxxx>
wrote:

> Assuming that there is just one BookBinding for all books with the same
> title by the same author and with the same binding, and also assuming that
> all books with the same title by the same author are in ** contiguous**
> bindings (which is the case with the provided document), then this XPath
> 2.0 expression selects the wanted Book elements. At least for me it seems
> less complex and more understandable than the originally provided expression
>
>      "for $b in
>        /*/*/Book[Author = ../following-sibling::*[1]/Book/Author
>                  and Title = ../following-sibling::*[1]/Book/Title
>                  and not(Binding = ../following-sibling::*[1]/Book/Binding)
>                     ][1],
>        $binding in distinct-values(/*/*/Book[Author = $b/Author and Title
> = $b/Title]/Binding)
>          return
>            /*/*/Book[Author = $b/Author and Title = $b/Title and Binding =
> $binding][1]
>
>
> On Thu, May 2, 2019 at 5:55 AM Costello, Roger L. costello@xxxxxxxxx <
> xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
>> Hello XPath experts!
>>
>> At the bottom of this message is my XML document. I need an XPath 2.0
>> expression that returns the result of this query:
>>
>>         Are there any book titles with more than
>>         one binding? If yes, then show the first book
>>         for each binding.
>>
>> For the below XML document, the query should return these two books:
>>
>> <Book>
>>     <Author>Sally Smith</Author>
>>     <Title>XYZ</Title>
>>     <Binding>hardcover</Binding>
>>     <Count>1</Count>
>>     <Description>lo lo lo ..</Description>
>> </Book>
>> <Book>
>>     <Author>Sally Smith</Author>
>>     <Title>XYZ</Title>
>>     <Binding>softcover</Binding>
>>     <Count>1</Count>
>>     <Description>do do do ..</Description>
>> </Book>
>>
>> Notice that the two books have the same author and title but different
>> binding (hardcover versus softcover).
>>
>> This XPath 2.0 expression seems to work:
>>
>> for $i in /Bookstore/BookTitle/Book[1],
>>     $j in /Bookstore/BookTitle/Book[1] return
>>         if (($i ne $j)
>>             and ($i/Author eq $j/Author)
>>             and ($i/Title eq $j/Title)
>>             and ($i/Binding ne $j/Binding)
>>             and ($i = $j/preceding::Book))
>>         then ($i, $j)
>>         else ()
>>
>> That expression seems awfully complicated. Is there a simpler expression?
>> If there isn't a simpler expression, then do you see anything missing in
>> the expression (i.e., something that the expression doesn't take into
>> consideration)?  /Roger
>>
>> <Bookstore>
>>     <BookTitle>
>>         <Book>
>>             <Author>John Doe</Author>
>>             <Title>ABC</Title>
>>             <Binding>hardcover</Binding>
>>             <Count>1</Count>
>>             <Description>da da da ..</Description>
>>         </Book>
>>         <Book>
>>             <Author>John Doe</Author>
>>             <Title>ABC</Title>
>>             <Binding>hardcover</Binding>
>>             <Count>2</Count>
>>             <Description>za za za ..</Description>
>>         </Book>
>>     </BookTitle>
>>     <BookTitle>
>>         <Book>
>>             <Author>John Doe</Author>
>>             <Title>Foo</Title>
>>             <Binding>softcover</Binding>
>>             <Count>1</Count>
>>             <Description>na na na ..</Description>
>>         </Book>
>>     </BookTitle>
>>     <BookTitle>
>>         <Book>
>>             <Author>Sally Smith</Author>
>>             <Title>XYZ</Title>
>>             <Binding>hardcover</Binding>
>>             <Count>1</Count>
>>             <Description>lo lo lo ..</Description>
>>         </Book>
>>         <Book>
>>             <Author>Sally Smith</Author>
>>             <Title>XYZ</Title>
>>             <Binding>hardcover</Binding>
>>             <Count>2</Count>
>>             <Description>ho ho ho ..</Description>
>>         </Book>
>>     </BookTitle>
>>     <BookTitle>
>>         <Book>
>>             <Author>Sally Smith</Author>
>>             <Title>XYZ</Title>
>>             <Binding>softcover</Binding>
>>             <Count>1</Count>
>>             <Description>do do do ..</Description>
>>         </Book>
>>     </BookTitle>
>> </Bookstore>

Current Thread