1

I am binding to an XML document in an XAML TextBlock statement and here is my XML document:

<Library>
    <Category Name="fiction">
        <Author Name="john Doe">
            <Book Title="Book A"/>
            <Book Title="Book B"/>
        </Author>
        <Author Name="Jane Doe"/>
    </Category>
    <Category Name="non-fiction"/>
    <Category Name="reference"/>
</Library>

In my xaml code, I can successfully bind to the Author "John Doe" using the following

Text="{Binding XPath=(/Library/Category/Author)[1]/@Name}" // Returns 'John Doe'.

However, if I try and bind to the first Book title (Book A) by John Doe using any of the following XPath statements, I get nothing.

Text="{Binding XPath=(/Library/Category/Author)[1]/(Book)[1]/@Title}" // Empty

Text="{Binding XPath=((/Library/Category/Author)[1]/Book)[1]/@Title}" //  Empty

Text="{Binding XPath=(/Library/Category/Author)[1]/Book[1]/@Title}" // Empty

Can someone tell me the correct syntax? Ideally, I want to be able to specify the Author by name rather index. Something like:

Text="{Binding XPath=((/Library/Category/Author)[@Name='john Doe']/Book)[1]/@Title}" //  Empty
Ted1391
  • 139
  • 3
  • 12

1 Answers1

0

According to the XML sample posted, Book elmeents aren't children of Author but siblings. So in this case, you are supposed to use following-sibling axis instead :

  1. /Library/Category/Author[1]/following-sibling::Book[1]/@Title

  2. /Library/Category/Author[@Name='john Doe']/following-sibling::Book[1]/@Title *

Anyway, I would recommend changing the XML structure if possible. Place Book elements inside the corresponding Author parent element. This kind of structure is way easier to deal with using XPath. :

<Library>
    <Category Name="fiction">
        <Author Name="john Doe">
            <Book Title="Book A"/>
            <Book Title="Book B"/>
        </Author>
        <Author Name="Jane Doe"/>
    </Category>
    <Category Name="non-fiction"/>
    <Category Name="reference"/>
</Library>

And the XPath for the corrected XML :

  1. /Library/Category/Author[1]/Book[1]/@Title

  2. /Library/Category/Author[@Name='john Doe']/Book[1]/@Title *

*: Notice that XML & XPath are case-sensitive, here I assume you have 'john Doe' instead of proper-cased 'John Doe'.

har07
  • 88,338
  • 12
  • 84
  • 137
  • Thanks, I changed the XML structure as you have listed, as having the book elements as children was my original intent. However, after making the correction (and fixing the case on 'john'), still none of the shown XPath statements work. Do any of these seem correct? – Ted1391 Aug 02 '15 at 07:28
  • @TedN `/Library/Category/Author[@Name='john Doe']/Book[1]/@Title`. Tested [here](http://www.freeformatter.com/xpath-tester.html) against the XML in my answer and worked. – har07 Aug 02 '15 at 07:33
  • It will work there but not in the context of a binding statement. For example: does not work and gives a syntax error. So I have tried many various formats as shown above. – Ted1391 Aug 02 '15 at 16:49
  • 1
    @TedN you need to escape some characters in that case, see [1](http://stackoverflow.com/questions/23131068/error-in-xpath-binding-in-xaml/23131376#23131376) or [2](http://stackoverflow.com/questions/3090614/xpath-equality-expression-value-in-xaml-errors-%D0%A1-wpf?lq=1) – har07 Aug 03 '15 at 01:08
  • 1
    Using the escape characters was the key to the problem Text="{Binding XPath=/Library/Category/Author[@Name\=\'john Doe\']/Book[1]/@Title}" Can you turn this into and answer so I can mark your answer as correct? – Ted1391 Aug 08 '15 at 02:51