What's the most concise method to validate this xml report?

I have the attached xml "message" that contains a report I need to validate against the data contained in the server database. I have been working on it for a while and I am using a few foreach loops to handle the levels.

I'm fine with the way I am actually validating the data itself, but...

I think there has to be a better way to iterate through the xml nodes to validate the data.

What is the most concise method to interate throug the xml when it has varying levels like the attached xml?
<Message message_type="data_validation" store_id="206" register_id="1">
  <Reports>
    <Report name="TSR" generated="03/20/2011 14:00:53" fromDate="03/19/2011" throughDate="03/19/2011" reportingRegisters="1" remote_synch_key="519181">
      <Section name="Section1">
        <Field name="Field1" value="$600.79" />
        <Field name="Field2" value="$600.79" />
      </Section>
      <Section name="Section 2">
        <Field name="Field3" value="$0.00" />
      </Section>
      <Section name="Section3">
        <Subsection name="Section4">
          <Field name="Field5" qty="3" value="($18.64)" />
          <Field name="Field6" qty="3" value="($18.64)" />
        </Subsection>
        <Subsection name="Section4">
          <Field name="field2" qty="5" value="($26.55)" />
          <Field name="field7" qty="4" value="($3.46)" />
        </Subsection>
        <Field name="field3" qty="12" value="($48.65)" />
        <Field name="field8" value="8.82" />
      </Section>
    </Report>
  </Reports>
</Message>

Open in new window

dgerlerAsked:
Who is Participating?
 
dimajConnect With a Mentor Commented:
A little correction:

Here's how your code should look:
public void SomeFunc (string str) {
  // please note that Load takes a Stream object or a file location
  XDocument doc = XDocument.Load(str);
  List<XElement> nodes = (from n in doc.Root.DescendantsAndSelf("Field")
                          select n).ToList();
}

Open in new window


Then, when you loop through your list of nodes, use 'Parent' property to identify the location where this node is in the tree. You can also test that before selecting the node. In this case your code would look like this:
 
public void SomeFunc (string str) {
  // please note that Load takes a Stream object or a file location
  XDocument doc = XDocument.Load(str);
  List<XElement> nodes = (from n in doc.Root.DescendantsAndSelf("Field")
                          where MyCriteriaIsNotMet(n)
                          select n).ToList();
}

private bool MyCriteriaIsNotMet(XElement node) {
  // do your node tests here
}

Open in new window

0
 
käµfm³d 👽Commented:
Is there a schema or DTD for this XML? There are several classes in .NET you can use to validate XML against a schema or DTD.
0
 
dimajCommented:
Take a look at Linq with XML. You can easily find any node you want and then validate them against your database.

The general idea is as follows:
XDocument doc = XDocument.Load("your xml stuff");

List<XElement> errors =
from report in doc.Root.DescendantsAndSelf("Report")
from section in report.DescendantsAndSelf("Section")
from subsection in section.DescendantsAndSelf("Subsection")
from field in subsection.DescendantsAndSelf("Field")
where DataIsInvalid(field)
select field).ToList();

Please note, that DataIsInvalid is a function that you must define which will test whether or not your data validates against your database.
At the end of this command, your 'errors' variable will contain all nodes that could not be validated.

Hope this will get you started.
0
Cloud Class® Course: SQL Server Core 2016

This course will introduce you to SQL Server Core 2016, as well as teach you about SSMS, data tools, installation, server configuration, using Management Studio, and writing and executing queries.

 
dgerlerAuthor Commented:
DescendentsAndSelf does not take any arguements. When left out, I get every node, not just field nodes.
0
 
dgerlerAuthor Commented:
By the way, I should be more clear. The "validation" is more a compare of he values to determine if they match.
0
 
dimajCommented:
DescendantsAndSelf should have an optional argument of node name.
As far as validation goes, your ' where' clause could be a function that takes current node and an expected value, then compare the two and return true or false.
0
 
dgerlerAuthor Commented:
OK.. What I really wanted was:

List<XElement> nodes = (from n in doc.Root.Descendants("Field")  select n).ToList();

Which gives me a List of the Field nodes.

then I am using

string currentField = node.Parent.Attribute("name").Value + " - " + node.Attribute("name").Value;

to get my identifier for the particular field to compare.
0
 
dimajCommented:
Ok, so that gives you either section out subsection... What is your "validation rule"?
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.