Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / XML / May 2005

Tip: Looking for answers? Try searching our database.

There MUST be a better way...

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
David Sterling - 14 Jun 2004 22:02 GMT
After much futzing about with the XML/XSD for the
Search.Response, I had to resort to this...

PLEASE Tell me there is a better way!

        private void ExecuteAQuery(string
strLookingForWhat)
        {
            // create the area service object
            SearchWebService.QueryService
queryService = CreateSearchService();
            const string keywordQueryTemplate
= "<?xml version=\"1.0\" encoding=\"utf-8\" ?><QueryPacket
xmlns=\"urn:Microsoft.Search.Query\" Revision=\"1000
\"><Query
domain=\"QDomain\"><SupportedFormats><Format>urn:Microsoft.
Search.Response.Document.Document</Format></SupportedFormat
s><Context><QueryText language=\"en-US\"
type=\"STRING\">query_text_placeholder</QueryText></Context
></Query></QueryPacket>";
            const string SQLQueryTemplate    
= "<?xml version=\"1.0\" encoding=\"utf-8\" ?><QueryPacket
xmlns=\"urn:Microsoft.Search.Query\" Revision=\"1000
\"><Query domain=\"s2003e:81
\"><SupportedFormats><Format>urn:Microsoft.Search.Response.
Document.Document</Format></SupportedFormats><Context><Quer
yText language=\"en-US\"
type=\"MSSQLFT\">query_text_placeholder</QueryText></Contex
t><Range><StartAt>1</StartAt><Count>5</Count></Range></Quer
y></QueryPacket>";
            string queryString =
keywordQueryTemplate.Replace("query_text_placeholder",
strLookingForWhat);
            // DOES NOT WORK (Internal System
Error Returned):
            string queryString2 =
SQLQueryTemplate.Replace("query_text_placeholder",
strLookingForWhat);
            // Init results:
            string queryResults = null;
            try
            {
                queryResults =
queryService.Query(queryString);
            }
            catch (Exception ExSheesh)
            {
                throw (ExSheesh);
            }
            //
            // Load the returned XML into a
Document - first create a New XML Document,
            // apply the Response.XSD schema,
then load the XML from the text received:
            //
            XmlDataDocument NewXmlDoc = new
XmlDataDocument();
            // Causes error:
            //NewXmlDoc.DataSet.ReadXmlSchema
("e:\\SPSSites\\SPSLive\\Response.xsd");
            //NewXmlDoc.DataSet.ReadXmlSchema
("/Response.xsd");
            NewXmlDoc.LoadXml(queryResults);
            string XmlDocTableName =
NewXmlDoc.NameTable.ToString();
            //
            // Get the status:
            //
            XmlNodeList
Response_StatusNodeList = NewXmlDoc.GetElementsByTagName
("Status");
            string ActualStatus =
Response_StatusNodeList[0].ChildNodes[0].Value;

            XmlElement TheRootElement =
NewXmlDoc.DocumentElement;

            XmlNodeList RangeNodeReference =
NewXmlDoc.GetElementsByTagName("Range");
            XmlNodeList
RangeNodeContentsReference = RangeNodeReference
[0].ChildNodes;

            DataSet PsuedoResultsDS = new
DataSet();
            DataTable PsuedoResultsTable = new
DataTable("SearchResults");
            //
            // Add the columns:
            //
            DataColumn PRTitle = new DataColumn
("Title",System.Type.GetType("System.String"));
            DataColumn PRLinkUrl = new
DataColumn("LinkUrl",System.Type.GetType("System.String"));
            DataColumn PRFileExt = new
DataColumn("FileExt",System.Type.GetType("System.String"));
            DataColumn PRDescription = new
DataColumn("Description",System.Type.GetType
("System.String"));
            DataColumn PRFileDate = new
DataColumn("FileDate",System.Type.GetType
("System.DateTime"));
            PsuedoResultsTable.Columns.Add
(PRTitle);
            PsuedoResultsTable.Columns.Add
(PRLinkUrl);
            PsuedoResultsTable.Columns.Add
(PRFileExt);
            PsuedoResultsTable.Columns.Add
(PRDescription);
            PsuedoResultsTable.Columns.Add
(PRFileDate);

            PsuedoResultsDS.Tables.Add
(PsuedoResultsTable);
            //
            // Now check the nodes within
<Range> looking for the result set <Results>:
            //
            string sTotalItemsReturned = "";
            int iTotalItemsReturned = 0;
            //
            foreach(XmlNode ARangeNode in
RangeNodeContentsReference)
            {
                if(ARangeNode.Name
== "StartAt")
                {
                }
                if(ARangeNode.Name
== "Count")
                {
                }
                //
                // When we find the
<TotalAvailable> node, this tells us how many rows we have
                // to process:
                //
                if(ARangeNode.Name
== "TotalAvailable")
                {
                    //
                    // Now get how
many were returned (in <Range><TotalAvailable>) and
                    // convert it to
use for an index:
                    //
                    XmlNodeList
TotalValNode = NewXmlDoc.GetElementsByTagName
("TotalAvailable");
               
    sTotalItemsReturned = TotalValNode[0].ChildNodes
[0].InnerText;
                    if
(sTotalItemsReturned != "")
                    {
                   
    iTotalItemsReturned = Convert.ToInt32
(sTotalItemsReturned);
                    }
                }
                //
                // When we find the
<Results> node (should be right after TotalAvailable),
                // our results are in the
nodes below:
                //
                if(ARangeNode.Name
== "Results")
                {
                    //
                    // Get a pointer
to the Row:
                    //
                    XmlNodeList
ResultRowNodes = ARangeNode.ChildNodes;
                    XmlElement
TheActualResultRecord = (XmlElement)ResultRowNodes[0];
                    //
                    // Make sure we
got something:
                    //
                    if
(iTotalItemsReturned > 0)
                    {
                        //
                        // We did -
each now represents a Row - pull the data out and put
                        // it into
a new record to save to the dataset:
                        //
                        for (int
x=0; x < iTotalItemsReturned; x++)
                        {
                       
    XmlNodeList ColumnsNodes =
TheActualResultRecord.ChildNodes;
                       
    DataRow NewDataRow = PsuedoResultsDS.Tables
["SearchResults"].NewRow();
                       
    NewDataRow["Title"] = ColumnsNodes[0].InnerText;
                       
    string T0 = ColumnsNodes[0].Name;
                       
    string T1 = ColumnsNodes[0].InnerText;
                       
    NewDataRow["LinkUrl"] = ColumnsNodes[1].ChildNodes
[0].InnerText;
                       
    string T2 =  ColumnsNodes[1].ChildNodes
[0].InnerText;
                       
    NewDataRow["FileExt"] = ColumnsNodes[1].ChildNodes
[0].Attributes[0].InnerText;
                       
    string T3 = ColumnsNodes[1].ChildNodes
[0].Attributes[0].InnerText;
                       
    NewDataRow["Description"] = ColumnsNodes
[2].InnerText;
                       
    string T4 = ColumnsNodes[2].InnerText;
                       
    NewDataRow["FileDate"] = Convert.ToDateTime
(ColumnsNodes[3].InnerText);
                            //
                            //
Add the new row:
                            //
                       
    PsuedoResultsDS.Tables["SearchResults"].Rows.Add
(NewDataRow);
                        }
                    }

                }
               
            }
            dataGrid1.DataSource =
PsuedoResultsDS;
            dataGrid1.SetDataBinding
(PsuedoResultsDS,"SearchResults");

        }
Dino Chiesa [Microsoft] - 16 Jun 2004 01:32 GMT
that code makes my eyes hurt.  Can you tell me what is the problem, in
english?
-D

> After much futzing about with the XML/XSD for the
> Search.Response, I had to resort to this...
[quoted text clipped - 6 lines]
> // lots and lots of code here.
> }
David Sterling - 16 Jun 2004 02:01 GMT
Yeah, basically this:

I'm getting back the Response from a query to a search service. I have
an inner data set (results) that I want; I have tried and tried to find
the correct way to map the XSD to no avail - (including using a
DataSet).

Alternative: I manually traverse through the XML Nodes until I find the
Results, then loop through and move the data items into a data set.

Gotta be a much better way!
David Sterling - 16 Jun 2004 02:11 GMT
Yeah, basically this:

I'm getting back the Response from a query to a search service. I have
an inner data set (results) that I want; I have tried and tried to find
the correct way to map the XSD to no avail - (including using a
DataSet).

Alternative: I manually traverse through the XML Nodes until I find the
Results, then loop through and move the data items into a data set.

Gotta be a much better way!
Dino Chiesa [Microsoft] - 16 Jun 2004 16:25 GMT
ok, you are getting a respoonse from a service.
The response is a System.Data.DataSet?   is that right?

eg, in the client side you do something like this:
   System.Data.DataSet ds= svc.MethodCall();

and in the server side you do somehting like this:
  [WebMethod]  public DataSet MethodCall() {
    DataSet ds= new DataSet();
    ds.Fill(...);
    return ds;
  }

And you are trying to get that Dataset to do ...what, exactly  ?

I see that you have resorted to manually parsing the XML, and I understand
why you want to avoid doing this.

But I don't understand what works and what does not work?   and just why you
have to manually parse it?

-D

> Yeah, basically this:
>
[quoted text clipped - 10 lines]
> *** Sent via Devdex http://www.devdex.com ***
> Don't just participate in USENET...get rewarded for it!
David Sterling - 16 Jun 2004 21:35 GMT
TO clarify as well...

The results I am getting are from using the SPS Search service - this
produces XML (not a dataset) from Microsoft.Search.Response using
QueryService. Thus why I tried to load the XML Doc and apply XSD to it
(catastrophic error).

David M. Sterling
CEO/Principal Consultant
Sterling International Consulting Group
david_sterling@sterling-consulting.com
David Sterling - 16 Jun 2004 21:35 GMT
I am trying to use the Results as a feed for creating data for a
DataGrid to use for other purposes.

If I could get a DataSet out of Response I'd glady use that, however, I
cannot apply even the MS provided XSD. And thanks, there is no
documentation (other than the schema - lite reading for sure) regarding
this or even use of the search.

Only way I figured out the way I did it was by trial and error and code
snippets I'd found along the way - the various books I have from MS and
the half mil worth of others from Wrox, etc. show none of this. 2 days
to get to that as it is...(and they wonder why we get to hating
development!) - used to be you'd have to figure out the logic - now you
fumble around in the dark for days to get what should take 20 minutes to
do...

The

David M. Sterling
CEO/Principal Consultant
Sterling International Consulting Group
david_sterling@sterling-consulting.com
Dino Chiesa [Microsoft] - 16 Jun 2004 23:19 GMT
I can understand your frustration.

I don't know SPS Search service, but I think I get the idea.
Can you send me some example XML from a reasonable search?

You can try to manually build a DataSet but that may not be worthwhile if
all you want is to display it. You are aware that you can also bind an array
of objects to the datagrid and display the values of the properties ?  It
may be much simpler for you.

-D

> I am trying to use the Results as a feed for creating data for a
> DataGrid to use for other purposes.
[quoted text clipped - 21 lines]
> *** Sent via Devdex http://www.devdex.com ***
> Don't just participate in USENET...get rewarded for it!
David Sterling - 17 Jun 2004 09:09 GMT
Sure...

Again, this is a response from the queryService using an XML query - the
returned XML looks like this:

<?xml version=\"1.0\" encoding=\"utf-16\"?>\n <ResponsePacket
xmlns=\"urn:Microsoft.Search.Response\">\n
<Response domain=\"QDomain\">\n    
<Copyright>Microsoft (c) Office
SharePoint (tm) Portal Server 2003</Copyright>\n
<Range>\n
<StartAt>1</StartAt>\n
<Count>1000</Count>\n
<TotalAvailable>2</TotalAvailable>\n
<Results>\n
<Document type=\"Portal content\" relevance=\"2\"
xmlns=\"urn:Microsoft.Search.Response.Document\">\n
    <Title>Microsoft SharePoint Products and Technologies Web
site</Title>\n
    <Action>\n
        <LinkUrl
size=\"0\">http://s2003e:81/moreinfo.aspx?ID=921F8F99-6DE3-4553-9A2B-208
FB4E9D5F9&amp;TargetUrl=http://r.office.microsoft.com/r/rlidMsSharePoint
?clid=en-us</LinkUrl>\n
    </Action>\n
    <Description>Microsoft SharePoint Products and Technologies home
page</Description>\n
    <Date>2004-03-18T23:00:20</Date>\n
</Document>\n
<Document type=\"Portal content\" relevance=\"2\"
xmlns=\"urn:Microsoft.Search.Response.Document\">\n
    <Title>Listing 1</Title>\n
    <Action>\n
        <LinkUrl fileExt=\"aspx\"
size=\"0\">http://s2003e:81/moreinfo.aspx?ID=5DB56241-D458-4F91-BA3E-B2A
9CF3B87C9&amp;TargetUrl=http://s2003e:81/txtlstvw.aspx?LstID=5db56241-d4
58-4f91-ba3e-b2a9cf3b87c9</LinkUrl>\n
    </Action>\n
    <Description>\n          </Description>\n
    <Date>2004-03-18T23:00:20</Date>\n
</Document>
</Results>\n
</Range>\n
<Status>SUCCESS</Status>\n
</Response>\n
</ResponsePacket>

Note: The \n is in the response.

David M. Sterling
CEO/Principal Consultant
Sterling International Consulting Group
david_sterling@sterling-consulting.com
David Sterling - 17 Jun 2004 09:09 GMT
One other thing: The goal is not to use a Dataset per se; what I am
using this for is to locate documents by the URL; using the consolidated
list (the response), the user can select items to be moved off for
archive - best done through a DataGrid.

David M. Sterling
CEO/Principal Consultant
Sterling International Consulting Group
david_sterling@sterling-consulting.com
Dino Chiesa [Microsoft] - 18 Jun 2004 20:03 GMT
Ok, here's what I did and it seems to get pretty close without too much
effort.

1. go to msdn to get the various schema, there are 4:

Response
http://msdn.microsoft.com/library/en-us/rssdk/html/rsxsdResponse.asp

Response.Document
http://msdn.microsoft.com/library/en-us/rssdk/html/rsxsdResponseDocument.asp

Types
http://msdn.microsoft.com/library/en-us/rssdk/html/rsxsdTypes.asp

You may also need Response Content, Response Form (depending on what your
queries return).  eg
http://msdn.microsoft.com/library/en-us/rssdk/html/rsxsdResponseContent.asp
http://msdn.microsoft.com/library/en-us/rssdk/html/rsxsdResponseForm.asp

Save each of these schema to a separate XSD file .

----
2.
modify the Response schema.  The Response schema "Results" field is typed as
"anything" (xsd:any).  But if you are doing sharepoint searches, it will
likely be a combination of Document, Content, and Form.  The sample you
showed me had 2 results, both were documents.  Your other queries may return
something else.

In any case I replaced this:
<xsd:complexType name="ResultCollectionType">
 <xsd:annotation>
  <xsd:documentation>Defines a set of results, in any format
supported.</xsd:documentation>
 </xsd:annotation>
 <xsd:choice maxOccurs="unbounded">
  <xsd:any namespace="##other">
   <xsd:annotation>
    <xsd:documentation>Any element in another namespace.  Elements here
will be in any results format supported by the client.  Office will support
the Form, Document, and Content results types.</xsd:documentation>
   </xsd:annotation>
  </xsd:any>
 </xsd:choice>
</xsd:complexType>

with this:

<xsd:complexType name="ResultCollectionType">
 <xsd:annotation>
  <xsd:documentation>Defines a set of results, in any format
supported.</xsd:documentation>
 </xsd:annotation>
 <xsd:choice maxOccurs="unbounded">
                   <xsd:element minOccurs="0" maxOccurs="unbounded"
ref="doc:Document" />
                   <xsd:element minOccurs="0" maxOccurs="unbounded"
ref="content:Content" />
 </xsd:choice>
</xsd:complexType>

and saved that doc to Microsoft.Search.Response-Modified.xsd

----
3.  generate classes that correspond to this schema using the xsd.exe
utility.  here's what I did:

xsd.exe  /namespace:sps /c Microsoft.Search.Response-Modified.xsd
Microsoft.Search.Response.Document.xsd Microsoft.Search.Types.xsd
Microsoft.Search.Response.Content.xsd

(the above all on one line)

This produces a source file that has a really really long name.  I renamed
it to (ResponsePacket.cs)

----
4.
You can now de-serialize directly from the stream, or from a file as shown
here:
     sps.ResponsePacket packet;
     string path = "Response-Pretty.xml";
     XmlSerializer s1 = new XmlSerializer(typeof(sps.ResponsePacket));
     System.IO.FileStream fs = new System.IO.FileStream(path,
System.IO.FileMode.Open);
     packet= (sps.ResponsePacket) s1.Deserialize(fs);

----
5. accessing the fields is done like this

     System.Console.WriteLine("Response Packet contains {0} Items ",
packet.Response.Length);
     for (int i=0; i < packet.Response.Length; i++) {
       System.Console.WriteLine("Item {0}: ", i);
       System.Console.WriteLine("  Copyright: {0}",
packet.Response[i].Copyright);
       System.Console.WriteLine("  Status: {0}",
packet.Response[i].Status);
       System.Console.WriteLine("  domain: {0}",
packet.Response[i].domain);
       if (packet.Response[i].Range!= null) {
         System.Console.WriteLine("  Range: ( {0} items)",
packet.Response[i].Range.Length);
         for (int j=0; j < packet.Response[i].Range.Length; j++) {
           System.Console.WriteLine("    Item: {0}", j);
           System.Console.WriteLine("      StartAt: {0}",
packet.Response[i].Range[j].StartAt);
           System.Console.WriteLine("      Count: {0}",
packet.Response[i].Range[j].Count);
           System.Console.WriteLine("      TotalAvailable: {0}",
packet.Response[i].Range[j].TotalAvailable);
           if (null != packet.Response[i].Range[j].Results) {
             System.Console.WriteLine("      Results: ({0} items)",
packet.Response[i].Range[j].Results.Length);

             for (int k=0; k < packet.Response[i].Range[j].Results.Length;
k++) {
               System.Console.WriteLine("        Item: {0}", k);
               if (packet.Response[i].Range[j].Results[k] is sps.Document)

ShowDocument((sps.Document)packet.Response[i].Range[j].Results[k]);  //
shows Title, relevance, Date, etc
               else if (packet.Response[i].Range[j].Results[k] is
sps.Content)

ShowContent((sps.Content)packet.Response[i].Range[j].Results[k]);  //
similar
             }
           }
         }
       }
     }

----
6.
What you want to do is, I think, bind the list of Documents
(packet.Response[i].Range[j].Results ) to a DataGrid.   The problem is that
objects in an array must have public properties if they are to be bound to a
DataGrid.  And the generated code for the Document type does not expose
public properties.

See this article
http://msdn.microsoft.com/library/en-us/dnexxml/html/xml01202003.asp , about
30% down, for a brief discussion for how to work around this.

-Dino

> One other thing: The goal is not to use a Dataset per se; what I am
> using this for is to locate documents by the URL; using the consolidated
[quoted text clipped - 8 lines]
> *** Sent via Devdex http://www.devdex.com ***
> Don't just participate in USENET...get rewarded for it!
Daniel Cazzulino [MVP XML] - 28 Jun 2004 17:35 GMT
Instead of manually modifying the huge file that will be generated, you can
perform a search & replace in VS with regular a expression as explained in
http://weblogs.asp.net/cazzu/archive/2003/08/26/25460.aspx, and you'll get
all public properties and be ready to data bind to the DataGrid

Signature

Daniel Cazzulino [MVP XML]
Clarius Consulting SA
http://weblogs.asp.net/cazzu
http://aspnet2.com

> Ok, here's what I did and it seems to get pretty close without too much
> effort.
[quoted text clipped - 5 lines]
>
> Response.Document

http://msdn.microsoft.com/library/en-us/rssdk/html/rsxsdResponseDocument.asp

> Types
> http://msdn.microsoft.com/library/en-us/rssdk/html/rsxsdTypes.asp
>
> You may also need Response Content, Response Form (depending on what your
> queries return).  eg

http://msdn.microsoft.com/library/en-us/rssdk/html/rsxsdResponseContent.asp
> http://msdn.microsoft.com/library/en-us/rssdk/html/rsxsdResponseForm.asp
>
[quoted text clipped - 138 lines]
> > *** Sent via Devdex http://www.devdex.com ***
> > Don't just participate in USENET...get rewarded for it!
Matthew Cosier - 04 May 2005 08:18 GMT
Maybe you should check out what I'm doing with my SharePoint Advanced
Search Tools (SAST):

http://matt.officeisp.net/
http://workspaces.gotdotnet.com/sast

Results will be XSLT formatted soon...

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.