Get XML node value if previous node value conditions are true (no loops)

XML example -

<?xml version="1.0"?>
<Root>
  <PhoneType dataType="string">
    <Value>CELL</Value>
  </PhoneType>
  <PhonePrimaryYn dataType="string">
    <Value>Y</Value>
  </PhonePrimaryYn>
  <PhoneNumber dataType="string">
    <Value>555-555-5554</Value>
  </PhoneNumber>
  <PhonePrimaryYn dataType="string">
    <Value>Y</Value>
  </PhonePrimaryYn>
  <PhoneType dataType="string">
    <Value>HOME</Value>
  </PhoneType>
  <PhoneNumber dataType="string">
    <Value>555-555-5555</Value>
  </PhoneNumber>    
</Root>

      

Without scrolling through each nodelist, can someone tell me (with LINQ-to-XML or other ways) how can I accomplish the following?

In the sample XML, you see two groups of groups "PhoneType", "PhonePrimaryYn" and "PhoneNumber". The first group of three refers to each other. The second group of three applies to the other, and so on.

Let's say that I want to know what a cell phone number is.

I get this cell phone number when "PhoneType" "Value" is "CELL", "PhonePrimaryYn" is "Y", I get "PhoneNumber" "Value" from "555-555-5554" ". You hope you have an idea.

I would like to know if it is possible to get this "PhoneNumber" value (for example a cell phone) without having to loop through each group of nodelists of a certain type.

Does anyone have any ideas?

+3


source to share


2 answers


UPDATE

Using XDocument vs XmlDocument I believe it does what you ask without using loops.

It depends on what the elements are in order

<PhoneType> <PhonePrimaryYN> <PhoneNumber>

string xml = "<?xml version=\"1.0\"?>" +
    "<Root>" + 
    "  <PhoneType dataType=\"string\">" + 
    "    <Value>CELL</Value>" + 
    "  </PhoneType>" + 
    "  <PhonePrimaryYn dataType=\"string\">" + 
    "    <Value>Y</Value>" + 
    "  </PhonePrimaryYn>" + 
    "  <PhoneNumber dataType=\"string\">" + 
    "    <Value>555-555-5554</Value>" + 
    "  </PhoneNumber>" + 
    "  <PhonePrimaryYn dataType=\"string\">" + 
    "    <Value>Y</Value>" + 
    "  </PhonePrimaryYn>" + 
    "  <PhoneType dataType=\"string\">" + 
    "    <Value>HOME</Value>" + 
    "  </PhoneType>" + 
    "  <PhoneNumber dataType=\"string\">" + 
    "    <Value>555-555-5555</Value>" + 
    "  </PhoneNumber>    " +
    "  <PhoneType dataType=\"string\">" +
    "    <Value>CELL</Value>" +
    "  </PhoneType>" +
    "  <PhonePrimaryYn dataType=\"string\">" +
    "    <Value>Y</Value>" +
    "  </PhonePrimaryYn>" +
    "  <PhoneNumber dataType=\"string\">" +
    "    <Value>555-555-9999</Value>" +
    "  </PhoneNumber>" + 
    "</Root>";

XDocument xDoc = XDocument.Parse(xml);
if (xDoc.Root != null)
{
    var tmp = (from item in xDoc.Root.Descendants()
                where item.Name == "PhoneType" && item.Value == "CELL"
                select new
                            {
                                PhoneNumber = item.NextNode.NextNode
                            }).ToList();

    for (int i = 0; i < tmp.Count; i++)
    {
        Console.WriteLine(((XElement)tmp[i].PhoneNumber).Value);
    }
}

      

Results:

555-555-5554
555-555-9999

      

OLD ANSWER

When I loaded your XML sample into XmlDocument

, I saw that this property InnerText

contains the following:



CELLY555-555-5554YHOME555-555-5555

      

From here I thought Regex would be a good method to extract CELL numbers using a template:

"CELL[NY](\\d{3}-\\d{3}-\\d{4})"

      

The pattern looks for the word "CELL" followed by "N" or "Y" followed by a phone number in the format ###-###-#####

. The phone number is in the capture group, and if a match is found, it can be accessed as shown in the following example.

I added another CELL entry to show that you can get all CELL numbers in your XML. Thus, the property InnerText

, XmlDocument

now looks like

CELLY555-555-5554YHOME555-555-5555CELLY555-555-9999

XmlDocument xmlDocument = new XmlDocument();
xmlDocument.LoadXml("<?xml version=\"1.0\"?>" +
    "<Root>" + 
    "  <PhoneType dataType=\"string\">" + 
    "    <Value>CELL</Value>" + 
    "  </PhoneType>" + 
    "  <PhonePrimaryYn dataType=\"string\">" + 
    "    <Value>Y</Value>" + 
    "  </PhonePrimaryYn>" + 
    "  <PhoneNumber dataType=\"string\">" + 
    "    <Value>555-555-5554</Value>" + 
    "  </PhoneNumber>" + 
    "  <PhonePrimaryYn dataType=\"string\">" + 
    "    <Value>Y</Value>" + 
    "  </PhonePrimaryYn>" + 
    "  <PhoneType dataType=\"string\">" + 
    "    <Value>HOME</Value>" + 
    "  </PhoneType>" + 
    "  <PhoneNumber dataType=\"string\">" + 
    "    <Value>555-555-5555</Value>" + 
    "  </PhoneNumber>    " +
    "  <PhoneType dataType=\"string\">" +
    "    <Value>CELL</Value>" +
    "  </PhoneType>" +
    "  <PhonePrimaryYn dataType=\"string\">" +
    "    <Value>Y</Value>" +
    "  </PhonePrimaryYn>" +
    "  <PhoneNumber dataType=\"string\">" +
    "    <Value>555-555-9999</Value>" +
    "  </PhoneNumber>" + 
    "</Root>");

Match match = Regex.Match(xmlDocument.InnerText, "CELL[NY](\\d{3}-\\d{3}-\\d{4})");
while (match.Success)
{
    Console.WriteLine(match.Groups[1]);
    match = match.NextMatch();
}

      

Results:

555-555-5554
555-555-9999

      

0


source


Personally, I would change how XML works so you have all the information for one phone number in one block like this

<phoneStructure>
   <type>CELL</type>
   <value>0123</value>
   <primary>false</primary>
</phoneStructure>

      

You can then use that XPath to select the entire phone structure where it is a cell phone, or change it to primary and then read the value from there.



//PhoneStructure[Type='Cell']

      

If you need more help with this, let me know.

0


source







All Articles