Home > Blockchain >  How to select first Value node of Textbox nodes using xpath?
How to select first Value node of Textbox nodes using xpath?

Time:09-22

 XmlNodeList changeValues = doc.SelectNodes("//x:Textbox[contains(@Name, 'Report_')]//x:Value", xmlnsManager);

*Edit Say a section of my XML file looks like this:

    <Textbox Name="Report_Banana">
       <TextRun>
          <Value>Banana</Value>
       </TextRun>
       <TextRun>
          <Value>Other thing</Value>
       </TextRun>
    </Textbox>
   <Textbox Name="Report_Apple">
       <TextRun>
          <Value>Apple</Value>
       </TextRun>
       <TextRun>
          <Value>Other thing</Value>
       </TextRun>
    </Textbox>

I want to only add the first value in each textbox to my list. So my list would contain Banana and Apple, and not the other things.

How can I edit my Xpath to do that? The Xpath works so far, but it's still picking up the Other Thing values.

I need to use X: as I am using a namespace in the root.

I have tried:

 XmlNodeList changeValues = doc.SelectNodes("//x:Textbox[contains(@Name, 'Report_')]//x:Value"[1], xmlnsManager);

But it picks up the unwanted values still.

Thanks in advance!

CodePudding user response:

Your whole XML is invalid, because the attribute values are not quoted.
So, your XML should rather be

<Textbox Name="Report_Banana">
  <Value>Banana</Value>
  <Value>Other thing</Value
</Textbox>
<Textbox Name="Report_Apple">
  <Value>Apple</Value>
  <Value>Other thing</Value
</Textbox>

And then, your XPath-1.0 could be

//Textbox[contains(@Name, 'Report_')]/Value[1]

which would select the first Value child of the Textbox element.
With the x: namespace given, it could look like

//x:Textbox[contains(@Name, 'Report_')]//x:Value[1]

And a namespace agnostic version would be

//*[local-name()="Textbox" and contains(@Name, 'Report_')]/*[local-name()="Value"][1]

All three XPath expressions should result in the same nodeset; of course, depending on the context.

CodePudding user response:

Assuming you have a root element (and not multiple root Textbox as shown in OP), you could use the following to get the first Value for each TextBox

//Textbox[contains(@Name, 'Report_')]/Value[1]
  • Related