1

I"m pulling down data from GetListItems using SP Web Services. I want as much data as possible since I'm storing that off into a local XML document. I'm also trying to create a TSV from the data.

The returned XML is something like this:

<rs:data ItemCount="896" xmlns:rs="urn:schemas-microsoft-com:rowset">
<z:row ows_A="1" ows_B="2" xmlns:z="#RowsetSchema" />

There's actually closer to 60+ attributes per row, and the problem is the returned attributes per "row" aren't consistent (e.g. some have 60, some have 67, some have 59, etc).

If I explicitly ask for the attributes by name, it's not a big deal:

foreach (System.Xml.XmlNode listItem in nodeListItems)
            {
 if (listItem.Name == "rs:data")
                {
                  for (int i = 0; i < listItem.ChildNodes.Count; i++)
                    {
                        if (listItem.ChildNodes[i].Name == "z:row")
                        {
                            wtSr.Append(listItem.ChildNodes[i].Attributes["ows_Title"].Value);
                            wtSr.Append("\t");

etc, etc.

I tried parsing through all the attributes using something like

for (int k = 0; k < listItem.ChildNodes[i].Attributes.Count; k++)
 {
                                    tmpWtCol =                                          listItem.ChildNodes[i].Attributes[k].Name.ToString().Replace("ows_", string.Empty).Replace("_", string.Empty);
                                    wtSr.Append(tmpWtCol + "\t");


                                    wtDidHeaders = true;
                                }

to get the possible attributes, but I realized it would only pick up the first row, which may or may not have the maximum attributes possible. I thought about parsing through the entire thing. Though it's unlikely, I also have no real way of knowing if the "biggest count" row contains every combination.

Is there a more elegant solution to with "null" (missing) attributes and determining all the attributes to create an acceptable "column list"?

4 Answers 4

1

If you have the flexibility to use an XmlReader you could do:

HashSet<string> attributeNames = new HashSet<string>();

xmlReader = listItem.CreateNavigator().ReadSubtree();

while (xmlReader.Read())
{
  if (xmlReader.NodeType == XmlNodeType.Element
    && xmlReader.Name == "rs:data")
  {  
    if (xmlReader.HasAttributes)
    {
      int attributeCount = xmlReader.AttributeCount;
      for (int i = 0; i < attributeCount; i++)
      {
        xmlReader.MoveToAttribute(i);
        attributeNames.Add(xmlReader.Name);
      }
    }
  }
}
Sign up to request clarification or add additional context in comments.

Comments

0

I think the core of your question is that you want to know the unique names of all of the attributes (excluding namespace declarations) that appear on those elements in your document in the #RowsetSchema namespace that are named row.

LINQ is your friend:

foreach (string s in doc.Descendants()
    .Where(x => x.Name.NamespaceName == "#RowsetSchema")
    .Attributes()
    .Where(x => !x.IsNamespaceDeclaration)
    .Select(x => x.Name.LocalName)
    .Distinct())
{
    Console.WriteLine(s);
}

Comments

0

Your best bet is to know the schema of the list you getting the items from. That way, you will be able to also find out the internal names of the fields (an in xml-format: the ows_ part).

3 Comments

+1 for steering the conversation towards the XML schema of the original poster's program's input.
You're making possibly three assumptions here: 1 - The submitter is unaware of the purpose or existence of an XML Schema. 2 - If they are aware, they haven't run into a situation which prevents/discourages them from tying their code to a schema version. 3 - Serializing the XML based on a schema would be efficient. If the submitter is working with 100Mb of XML, the last thing he wants to do is serialize it.
I didn't refer to XML schema, I meant the List schema. The data of value to the submitter will most probably be user-generated data which is stored in the SharePoint list. Knowing the internal names of these columns will help the submitter know what data to pull out from the XML.
0

Create a Serializable class to hold all the the document. (As JamesLove says, you need to know the schema XML document you're trying to parse.)

You can mark up the data-holding properties of your class with attributes like [XmlElement] (see more of them on MSDN) to control how the objects of your class is (de)serialized. The goal (achievable in many cases) is to mark it up so that (de)serialization can be done using just one call to XmlSerializer.

As a general rule, try to minimize the amount of custom, procedural-style XML-parsing routines in your code. XML serialization is not a feature, it is something end users and customers totally don't care about.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.