1

How to extract the value of /substance/text and /makers/text?

I am expecting the result to be

  1. Automation
  2. Test Record

I have tried many things for example:

  • //*[local-name()='text/@value']
  • //*[local-name()='substance']/text/text()
  • //*[local-name()='name'][1]
    (This works for first name element but if I use similar for text it doesn't work.)
  • //*[local-name()='text/@value'][1]
  • //*[local-name()='text'][1]
<health xmlns="http://test.com/sample">
    <substance>
        <name>substance</name>
        <text value="Automation"/>
    </substance>
    <user>
        <reference value="User/111111122"/>
    </user>
    <reaction>
        <makers>
            <name>makers</name>
            <text value="Test Record"/>
        </makers>
    </reaction>
</health>
Maddy
  • 674
  • 1
  • 7
  • 26
  • The examples of what you tried show that you're guessing, and you're not really understanding what any of these expressions mean. You need to do some reading to get a better grasp of the concepts! Clearly there's no element in your document whose name is 'text/@value' - that's not a legal name. – Michael Kay Dec 21 '21 at 14:31

1 Answers1

1

This XPath,

//*[local-name()='text']/@value

will select all of the value attributes of all text elements in the document, regardless of namespaces.

Note that it is better to account for namespaces than to defeat them in this manner. See How does XPath deal with XML namespaces?


Not working?

The provided XPath does select both @value attributes. If you're only seeing one, it's likely because you're passing the result on to an XPath 1.0 function that expects a single value and is defined to select the first member of a node-set when passed multiple values. See Why does XPath expression only select text of first element?


Still not working?

Here are two options for selecting the values individually rather than collectively:

  1. (//*[local-name()='text']/@value)[1]
    (//*[local-name()='text']/@value)[2]

  2. //*[local-name()='substance']/*[local-name()='text']/@value
    //*[local-name()='makers']/*[local-name()='text']/@value

kjhughes
  • 106,133
  • 27
  • 181
  • 240
  • Thanks it worked for the first `/substance/text` and I need to extract the value from `/makers/text` as well. How we can give the parent node in start? – Maddy Dec 21 '21 at 13:41
  • Actually I am storing each value into a variable and hence `//*[local-name()='text']/@value` returns `Automation` and stored in variable so now I have to get the second value somehow. Is there a way to pass the parent node in this expression? – Maddy Dec 21 '21 at 14:09
  • Some how both above options are not working. Option 2 didn't work at all while for option 1 when I changed the array to Option 1: `(//*[local-name()='text']/@value)[1] and (//*[local-name()='text']/@value)[2]` it worked for [1] but not for [2]. – Maddy Dec 21 '21 at 14:20
  • See updated answer. If the shown options are still not working for you, I suspect there's a difference between your posted and actual XML or an issue in how you're using the results returned by the XPath expressions. – kjhughes Dec 21 '21 at 14:31
  • 1
    Thanks for your help. It is working fine I had one mistake in my code so once I corrected it started working – Maddy Dec 21 '21 at 23:25