Reputation: 11
Not sure if the title is clear but basically I have some XML like the following:
<details>
<result id=1234567890>
<name>Test1</name>
</result>
<result id=5345345433>
<name>Test2</name>
</result>
<result id=9572385354>
<name>Test3</name>
</result>
What I'm trying to accomplish is to find the id attribute of using the known value of i.e. Test1 > 1234567890, Test2 > 5345345433, Test3 > 9572385354
Preferably by using xmllint but xmlstarlet is also an option.
Upvotes: 1
Views: 1229
Reputation: 1
something like this should work with xmlstarlet (worked for me) :
xmlstarlet sel --template --match "/details/result[name='Test1']" --value-of "@id" test.xml
Upvotes: 0
Reputation: 1
To answer the OP's question in full,
#/bin/bash
#
# how to use xmllint to get information from specific elements
# REQUIRES libxml2 (sorry Snow Leopard!)
mytestxml='
<details>
<result id="1234567890">
<name>Test1</name>
</result>
<result id="5345345433">
<name>Test2</name>
</result>
<result id="9572385354">
<name>Test3</name>
</result>
</details>
'
echo Test Document is :"$mytestxml"
echo Get the contents of the \''id'\' attribute of a specific \''result'\' element
query=\''string(/details/result[3]/@id)'\'
echo xpath query is "$query"
myresult=$(echo "$mytestxml" | xmllint --xpath 'string(/details/result[3]/@id)' - )
echo info returned is "$myresult"
echo ""
echo Get the specific \''result'\' node whose \''name'\' element is \"Test1\"
query=\''/details/result[name="Test1"]'\'
echo xpath query is "$query"
myresult=$(echo "$mytestxml" | xmllint --xpath '/details/result[name="Test1"]' - )
echo info returned is "$myresult"
echo ""
echo Get the \''id'\' attribute of the specific \''result'\' node whose \''name'\' element is \"Test1\"
query=\''string(/details/result[name="Test1"]/@id)'\'
echo combined xpath query is "$query"
myresult=$(echo "$mytestxml" | xmllint --xpath 'string(/details/result[name="Test1"]/@id)' - )
echo info returned is "$myresult"
xpath query is :
'string(/details/result[3]/@id)'
info returned is : 9572385354
xpath query is :
'/details/result[name="Test1"]'
info returned is :
<result id="1234567890">
<name>Test1</name>
</result>
combined xpath query is :
'string(/details/result[name="Test1"]/@id)'
info returned is 1234567890
Hope this proves useful to other's who find this page. :o)
Upvotes: 0
Reputation: 2063
Perhaps a simple grep & awk solution will work for you.
grep -B1 Test1 sample.xml | awk '/id=/{gsub(/[^0-9]+/, "", $0); print $0 }'
Upvotes: 0
Reputation: 19545
You can also use xmllint
:
xmllint --xpath "string(/details/result[name='Test1']/@id)" yourfile.xml
--xpath
: tells xmllint
to select using the xpath
syntax.
Details of the xpath
selector:
string(/details/result[name='Test1']/@id)
string()
: Make a string
/details/result
: select the result
child element of the details
element
[name='Test1']
: containing a name
node whose value is Test1
/@id
: id
attribute value (of the result
element)
Upvotes: 2
Reputation: 53
Input
First, your XML is invalid. Your id properties need to be qouted, and the details is not closed. Here is the revised input:
<details>
<result id="1234567890">
<name>Test1</name>
</result>
<result id="5345345433">
<name>Test2</name>
</result>
<result id="9572385354">
<name>Test3</name>
</result>
</details>
Result
The following will extract the specific id given the name property using xmlstarlet.
xmlstarlet sel -t -c "/details/result[name='Test1']" test.xml | grep -Po "(?<=id=\")[\d]*"
This will return
1234567890
You can also replace Test1 in the command with a variable.
var=Test1
xmlstarlet sel -t -c "/details/result[name='$var']" test.xml | grep -Po "(?<=id=\")[\d]*"
Breakdown
xmlstarlet sel -t -c "/details/result[name='$var']" test.xml
Select all name tags inside results matching $var.
| grep -Po "(?<=id=\")[\d]*"
Pipe the output to grep with Perl Regex to look for the id property and print all containing digits.
Upvotes: 2