-->

Select node by its text value in xmlstarlet

2019-02-14 01:44发布

问题:

I am trying to extract the value of the 'Value' node, where the 'Key' node is 'state' within a bash shell:

<FrontendStatus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" serializerVersion="1.1">
<script/>
 <State>
  <String>
   ...
   ...
  </String>
  <String>
   ...
   ...
  </String>
  <String>
   <Key>state</Key>
   <Value>WatchingLiveTV</Value>
  </String>
  <String>
   <Key>studiolevels</Key>
   <Value>1</Value>
  </String>
  <String>
   ...
   ...
  </String>
  <String>
   ...
   ...
  </String>
 </State>
</FrontendStatus>

I can extract the value if I reference the node directly:

$ xmlstarlet sel -t -m '/FrontendStatus[1]/State[1]/String[31]' -v Value <status.xml
WatchingLiveTV

But I would like to select it by the value of the 'Key' node instead

回答1:

This XPath will select Value of a State based on its Key equalling state:

/FrontendStatus/State/String[Key='state']/Value

Or, in xmlstarlet:

$ xmlstarlet sel -t -m "/FrontendStatus/State/String[Key='state']" -v Value <status.xml

Will return WatchingLiveTV as requested.



回答2:

I was able to find that node using the following XPath:

/FrontendStatus/State/String[Value = 'WatchingLiveTV']/Value

Which will return:

<Value>WatchingLiveTV</Value>

Note you could also use:

//String[Value = 'WatchingLiveTV']/Value

Which is slightly smaller.

To select the Value element and parent/siblings, you could use:

//String[Value = 'WatchingLiveTV']

Which returns:

<String>
  <Key>state</Key>
  <Value>WatchingLiveTV</Value>
</String>

Edit

I just re-read your original question. You would like to select the XML based on the value of the Key node. You can do this using the above, but changing the predicate from Value to Key:

//String[Key = 'state']/Value

@kjhughes has put this into the syntax format you're after.

I hope that helps.