0

I have an xml file like below:

<FileHeader>SampleFile</FileHeader>
<Name>aaaa</Name>
<Place>bufnkf</Place>
<Name> bjfbhj</Name>
<Place>bvdhbf</Place>
<FileFooter><Record>2</Record></FileFooter>

I want to extract the value of Record tag. Used sed command like below but it's not giving any output:

sed -n '/Record/{s/.*<Record>//;s/<\/Record.*//;p;}' filename

Any help on this please?

4
  • 3
    Does this answer your question? Parse XML to get node value in bash script?
    – Jim L.
    Nov 7, 2021 at 23:30
  • 2
    One issue you may have using XML tools to process that file is ... it's not valid XML
    – Bravo
    Nov 7, 2021 at 23:42
  • @Bravo Note that the only thing missing from the file to make it well-formed XMl is an arbitrarily named start-tag at the start and its corresponding end-tag at the end. This could be inserted on the fly with { echo '<tag>'; cat file.xml; echo '</tag>'; } | some_processing_command.
    – Kusalananda
    Nov 8, 2021 at 17:19
  • @they - yes, I know what's missing, that doesn't make the data in the question valid XML - which was my point - you can't simply use any xml tools to process the data in the question
    – Bravo
    Nov 8, 2021 at 23:09

1 Answer 1

1

The easiest way to get the FileFooter/Record node's value into a shell variable in a script is by using an XML parser like xmlstarlet.

The following assumes that the XML document is well-formed, which your example document isn't as it has multiple root tags (I'm presuming this is because you extracted the bits that you thought was most interesting). It also assumes that there is only one single FileFooter/Record node, otherwise, you would have to iterate over the values.

value=$( xmlstarlet sel -t -v '//FileFooter/Record' file.xml )

The //FileFooter/Record expression is the XPath of the node that we're interested in (actually the XPath of each FileFooter/Record node in the whole document). With sel -t -v, we tell xmlstarlet that we want to extract the value (-v) that we get from matching a particular or XPath (sel -t).

Since the data in the question is missing a root tag, you may run the below command on it to insert the missing tag on the fly, parse the corrected document, and extract the wanted value inte the shell variable value:

value=$( 
    { echo '<root>'; cat file.xml; echo '</root>'; } |
    xmlstarlet sel -t -v '//FileFooter/Record'
)

Assuming that the missing single root node is called root, you could also extract the value using xq (from https://kislyuk.github.io/yq/), an XML parser layer built around the JSON parser jq.

value=$( xq -r '.root.FileFooter.Record' file.xml )

You could instead use .[].FileFooter.Record if you don't want to type out the root node's name (this still assumes that FileFooter is a node directly under the root node, though).

The command converts your XML file into JSON. If your XML document looks something like the following:

<?xml version="1.0"?>
<root>
  <FileHeader>SampleFile</FileHeader>
  <Name>aaaa</Name>
  <Place>bufnkf</Place>
  <Name> bjfbhj</Name>
  <Place>bvdhbf</Place>
  <FileFooter>
    <Record>2</Record>
  </FileFooter>
</root>

The xq utility would convert it into the following JSON document:

{
  "root": {
    "FileHeader": "SampleFile",
    "Name": [
      "aaaa",
      "bjfbhj"
    ],
    "Place": [
      "bufnkf",
      "bvdhbf"
    ],
    "FileFooter": {
      "Record": "2"
    }
  }
}

xq then calls jq with the expression .root.FileFooter.Record, which extracts the value.

2
  • thank you for the reply but looks like the input file is in a wrong format and there is no end of line character to the last line and thats why sed is not picking up the record.
    – user500337
    Nov 8, 2021 at 16:59
  • @user500337 See added bit at the end of the first part of the answer, which correct the data in the question before parsing it. A missing newline character in the end does not affect an XML parser. You don't want to use sed for this as XML is not a line-oriented document format.
    – Kusalananda
    Nov 9, 2021 at 6:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .