I'm trying to query XML through XPATH but is having problem getting id() to work. I would like to get all the authors for a book, specifying the book ID.
Here's the XML.
<?xml version="1.0" encoding="utf-8" ?>
<bookstore xmlns="http://litemedia.se/BookStore.xsd">
<book id="ISBN9789170375033">
<title>I väntan på talibanerna</title>
<cover>http://image.bokus.com/images2/9789170375033_large</cover>
<author-ref id="A1" />
</book>
<book id="ISBN9789170372063">
<title>Sista resan till Phnom Penh</title>
<cover>http://image.bokus.com/images2/9789170372063_large</cover>
<author-ref id="A1" />
</book>
<book id="ISBN9789127121867">
<title>Vårt bröllop : Kronprinsessan Victoria och Prins Daniel 19 juni 2010</title>
<cover>http://image.bokus.com/images2/9789127121867_large</cover>
<author-ref id="A2 A3" />
</book>
<book id="ISBN9789189204966">
<title>Människa, människa</title>
<cover>http://image.bokus.com/images2/9789189204966_large</cover>
<author-ref id="A3" />
</book>
<author id="A1">
<name>Jesper Huor</name>
</author>
<author id="A2">
<name>Susanna Popova</name>
</author>
<author id="A3">
<name>Paul Hansen</name>
</author>
</bookstore>
And this is my schema.
<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="BookStore"
targetNamespace="http://litemedia.se/BookStore.xsd"
elementFormDefault="qualified"
xmlns="http://litemedia.se/BookStore.xsd"
xmlns:mstns="http://litemedia.se/BookStore.xsd"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
>
<xs:element name="bookstore">
<xs:complexType mixed="true">
<xs:sequence>
<xs:element name="book" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="title" type="xs:string" />
<xs:element name="cover" type="xs:anyURI" />
<xs:element name="author-ref">
<xs:complexType>
<xs:attribute name="id" type="xs:IDREFS"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="id" type="xs:ID" />
</xs:complexType>
</xs:element>
<xs:element name="author" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="name" type="xs:string" />
</xs:sequence>
<xs:attribute name="id" type="xs:ID" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
This is my code.
public IList<Author> GetAuthorsForBook(string isbn)
{
using (var xmlStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(XmlDataSourcePath))
using (var xsdStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(XsdDataSourcePath))
{
var doc = new XmlDocument();
// Load schema
var schema = XmlSchema.Read(xsdStream, SchemaEvents);
doc.Schemas.Add(schema);
// Load document
doc.Load(xmlStream);
// Load default namespace: bs
var nsmgr = new XmlNamespaceManager(doc.NameTable);
nsmgr.AddNamespace("bs", "http://litemedia.se/BookStore.xsd");
// We should be able to do this
// var path = string.Format("id(id('{0}')/bs:author-ref/@id)", isbn);
// but this will have to do
var path = string.Format("/bs:bookstore/bs:author/@id[contains(/bs:bookstore/bs:book[@id='{0}']/bs:author-ref/@id,.)]", isbn);
return doc.SelectNodes(path, nsmgr).Cast<XmlNode>()
.Select(node =>
new Author
{
Name = node.FirstChild.Value
}).ToList();
}
}
Since I've specified bookId and authorId as ID type in the schema I would like to be able to do the following.
var path = string.Format("id(id('{0}')/bs:author-ref/@id)", isbn);
This query always returns 0 elements. If I reduce it to id('ISBN9789127121867') that will also return 0 result, which indicates that id() doesn't work in my scenario. :(
At the moment I'm going for the following query, even if it's not as efficient as using id() would be, it does give me the results I need.
var path = string.Format("/bs:bookstore/bs:author/@id[contains(/bs:bookstore/bs:book[@id='{0}']/bs:author-ref/@id,.)]", isbn);
Have you ever had a similiar problem or any clue to what I might have done wrong? Thank you!
Mikael Lundin