views:

254

answers:

5

I have a collection of data stored in XDocuments and DataTables, and I'd like to address both as a single unified data space with XPath queries. So, for example, "/Root/Tables/Orders/FirstName" would fetch the value of the Firstname column in every row of the DataTable named "Orders".

Is there a way to do this without copying all of the records in the DataTable into the XDocument?

I'm using .Net 3.5

A: 

Are you looking for something similar to what I asked regarding XPath foreign keys?

dacracot
No, I don't think so. The DataTable's contents are not part of the XML document. They're in a different "back end storage". I'd like to have XPath see all the data as if it was all part of the same XDocument. I just found something about XStreamingElement, and I'm looking into that as a possibility
C. Lawrence Wenham
A: 

As the XPath recommendation says, "The primary purpose of XPath is to address parts of an XML document." It doesn't have any facility for addressing parts of more than one XML document. You'll have to build a single XML document if you want to do what you're trying to do.

Robert Rossney
A: 

You would have to merge your documents, or at lest perform the same transformations on all of your documents. You may consider moving your documents to a single DataTable, then filtering the DataTable if the XPath / XSLT is not do-able.

David Robbins
+1  A: 

.NETs XPath stuff operates on the IXPathNavigable interface. Every IXPathNavigable has a CreateNavigator() method that returns an IXPathNavigator.

In order to expose all of your data sources as one large document you would need to create a class implementing IXPathNavigable, containing all the xpath data sources. The CreateNavigator method should return a custom XPathNavigator that exposes the contents as one large data source.

Unfortunately, implementing this navigator is somewhat fiddly, and care must be taken especially when jumping between documents,

Oliver Hallam
+1  A: 

I eventually figured out the answer to this myself. I discovered a class in System.Xml.LINQ called XStreamingElement that can create an XML structure on-the-fly from a LINQ expression. Here's an example of casting a DataTable into an XML-space.

Dictionary<string,DataTable> Tables = new Dictionary<string,DataTable>();
// ... populate dictionary of tables ...
XElement TableRoot = new XStreamingElement("Tables",
    from t in Tables
    select new XStreamingElement(t.Key,
               from DataRow r in t.Value.Rows
               select new XStreamingElement("row",
                          from DataColumn c in t.Value.Columns
                          select new XElement(c.ColumnName, r[c])))))

The result is an XElement (TableRoot) with a structure similar to the following, assuming the dictionary contains one table called "Orders" with two rows.

<Tables>
    <Orders>
        <row>
            <sku>12345</sku>
            <quantity>2</quantity>
            <price>5.95</price>
        </row>
        <row>
            <sku>54321</sku>
            <quantity>3</quantity>
            <price>2.95</price>
        </row>
    </Orders>
</Tables>

That can be merged with a larger XElement/XDocument based hierarchy and queried with XPath.

C. Lawrence Wenham