0

I try to extract data from a xml file (which I named output.xml) on the command line (and then, if I manage to do it, put it in a script).

I've seen that the better tool to do that is XMLStarlet. However xmlstarlet sel -t -m "/entry/content" output.xml doesn't work.

Note: I tried for xmlstarlet el output.xml to check the Xpath structure of the file and it works.That means that the tool sees the elements.


I saw that there are 2 conditions to make XMLStarlet work:

1- The XML file should be well-formed. Stackoverflow related link

So I applied this command to create a well-formed file:

xmlstarlet fo -R output.xml >> good-output.xml

2- XML is very picky about the default namespace. If the document has it, declare it before selecting the elements or delete all the occurences of "xmlns" in the document. Stackoverflow related link

So I did:

$ cat good-output.xml | sed -e 's/ xmlns.*=".*"//g' >> very-good-output.xml

HOWEVER, even performing these two steps, I have another error, and don't know how to fix it... The terminal points to me the places I removed the namespaces and says "Namespace prefix app on collection is not defined". What I should do? With the namespaces it doesn't work and now it urges to put them again upon me...

Any help?

Screenshot of the original problem

Screenshot of the final problem

Community
  • 1
  • 1
Héloïse Chauvel
  • 502
  • 3
  • 6
  • 21
  • Okay, maybe I've understood why the terminal is blaming me. The tags where there is the error are formed like so: `word:anotherword` And it seems that this notation implies that we should find a xmlns attribute in that tag. But I don't know how I can delete these notations. I guess I have to use REGEX but I'm still not comfortable with it to do such action. – Héloïse Chauvel Apr 26 '17 at 16:19
  • If your document defines the namespaces you can use its prefixes in the XPath expressions, see also http://xmlstar.sourceforge.net/doc/UG/ch05.html. – npostavs Apr 26 '17 at 20:41
  • Thank you! I used `xmlstarlet sel -t -m "//_:content" -c . good-output.xml` and it gave me the corresponding tag. The only problem now is that I only want the content of the tag and not the tag itself + its content. How should I do? – Héloïse Chauvel Apr 27 '17 at 08:10
  • `-v` instead of `-c`. – npostavs Apr 27 '17 at 12:22
  • Yes it works. It works with `/text()` too. – Héloïse Chauvel Apr 27 '17 at 12:32

2 Answers2

4

So this is the final solution to retrieve the content of a XML file with multiple namespaces:

xmlstarlet sel -t -m "//_:content" -c . good-output.xml


npostavs thank you for guiding me.

I believed the fact that my first attempt gave me the tag besides the desired content was a problem, but actually in my case no. If it is the case for someone else, this is how to proceed:

xmlstarlet sel -t -m "/_:entry/_:content/text()" -c . output.xml

OR

xmlstarlet sel -t -m "/_:entry/_:content" -v . output.xml

Simplified:

xmlstarlet sel -t -v "/_:entry/_:content" output.xml

Héloïse Chauvel
  • 502
  • 3
  • 6
  • 21
0

Seems that the problems like this happens if the xml uses a different namespace. In these cases, one solution to overcome namespaces issues is to tell xmlstarlet the expected namespace value of the element:

xmlstarlet sel -N x='http://different.namespace.url/XMLSchema' -t -m '//x:YourElemHere' input.xml

daparic
  • 3,794
  • 2
  • 36
  • 38