how do edit complex xml file by sed - sed

this is the structure of xml file:
<test.file>
<set name="parameter1" serializeAs="String">
<value>True</value>
</set>
<set name="parameter2" serializeAs="String">
<value>True</value>
</set>
</test.file>
I want to edit value from True to False for Parameter2
when I use this command:
xmlstarlet ed -u //test.\file/set/value -v False filename
It is updating both value from True to False.
How can I control to edit the value only for name="parameter2"?
Thank u!

EDIT: Since OP is asking to make changes on a specific tag's value so changed code according to it.
xmlstarlet ed -u "//test.file/set[#name='parameter2']/value" -v "false" Input_file.xml
Following xmlstarlet command may help you here.
xmlstarlet ed -u "/test.file/set/value" -v "false" Input_file.xml
To do inplace update into xml file itself use following.
xmlstarlet ed -L -u "/test.file/set/value" -v "false" Input_file.xml

Related

How to perform UTF-8 encoding using xmlstarlet fo --encode option?

The synopsis for xmlstarlet fo says
XMLStarlet Toolkit: Format XML document
Usage: xmlstarlet fo [<options>] <xml-file>
where <options> are
-n or --noindent - do not indent
-t or --indent-tab - indent output with tabulation
-s or --indent-spaces <num> - indent output with <num> spaces
-o or --omit-decl - omit xml declaration <?xml version="1.0"?>
--net - allow network access
-R or --recover - try to recover what is parsable
-D or --dropdtd - remove the DOCTYPE of the input docs
-C or --nocdata - replace cdata section with text nodes
-N or --nsclean - remove redundant namespace declarations
-e or --encode <encoding> - output in the given encoding (utf-8, unicode...)
-H or --html - input is HTML
-h or --help - print help
When I run
cat unformatted.html | xmlstarlet fo -H -R --encode utf-8
I am returned the error message
failed to load external entity "utf-8"
In my limited experience, xmlstarlet fo especially, needs the stdin dash to work (better).
In your example, the 'unformatted.html' contents are piped to xmlstarlet.
But xmlstarlet fo doesn't 'see' the piped input, if you don't use a - (dash).
It assumes that the last argument (utf-8) is the filename ("external entity") whose contents you're trying to format. Obviously, there's no such file. Just to be on the safe side, I'd also enclose the encoding argument with double quotes, like so: "utf-8".
Altering your statement to
xmlstarlet fo -H -R --encode "utf-8" unformatted.html
should do the trick.
The cat is unnecessary, I'd think.

How to use rex command with REST api of splunk curl as client

i am trying to Extract new field from raw data by regular expression(rex command).My regular expression is working fine in splunk web search bar and getting results. But not not working with REST api curl as client.
i want to extract a field from a csv data set train.csv and want to give it name as "numbers"
curl -u admin:password -k https://localhost:8089/services/search/jobs -d search="search source=train.csv|rex field=_raw '^(?:\[^\"\\n\]*\"){2},\\w+,\\d+,\\d+,\\d+,\\d+,\\d+\\.\\d+,(?P<numbers>\[^,\]+)'| top numbers"
by executing this command i got sid
<?xml version="1.0" encoding="UTF-8"?>
<response>
<sid>1548238904.70</sid>
by after asking for result i am getting error
curl -u admin:password -k https://localhost:8089/services/search/jobs/1548238904.70/results
Error in 'rex' command: The regex ''^(?:\[^\n\]*){2}' does not extract anything. It should specify at least one named group. Format: (?<name>...).</msg>
what is named group ,why its working well in splunk search bar
i want result with "number" as column or new field
Looking at your SPL itself, it appears that you've got single quotes instead of double quotes in your rex, which is known to cause issues or no results.
Try the following approach of escaping double quotes instead:
$ curl -u 'username:password' -k https://dummy.splunk.url/services/search/jobs -d search="| stats count | eval foo=\"bar\" | rex field=foo \"\w(?<named>\w*)\" | table foo named"
When asking for the results back, you should see the following:
$ curl -u 'username:password' -k https://dummy.splunk.url/services/search/jobs/1548868781.39708/results
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 315 100 315 0 0 420 0 --:--:-- --:--:-- --:--:-- 420<?xml version='1.0' encoding='UTF-8'?>
<results preview='0'>
<meta>
<fieldOrder>
<field>foo</field>
<field>named</field>
</fieldOrder>
</meta>
<result offset='0'>
<field k='foo'>
<value><text>bar</text></value>
</field>
<field k='named'>
<value><text>ar</text></value>
</field>
</result>
</results>
Presuming the above approach is used, you should end up with a curl command as such:
curl -u admin:password -k https://localhost:8089/services/search/jobs -d search="search source=train.csv|rex field=_raw \"^(?:\[^\"\\n\]*\"){2},\\w+,\\d+,\\d+,\\d+,\\d+,\\d+\\.\\d+,(?P<numbers>\[^,\]+)\"| top numbers"

Using sed to change pom/xml element value with regular expressuib

I have an XML file and I used sed to change the value of the element "own.version":
<properties>
<own.version>1.1.77-SNAPSHOT</own.version>
</properties>
Sed statement:
cat pom.xml | sed -e "s%<own.version>${oldVersion}</own.version>%<own.version>${newVersion}</own.version>%" > pom.xml.transformed
Now my pom file is going to be more generic and properties that I want to change might be "*.own.version", e.g.:
<properties>
<a.own.version>1.1.77SNAPSHOT</a.own.version>
</properties>
How can I use a regulare expression with sed to change the value of *.own.version?
This one should work, it captures any prefix of "own.version".
sed "s%<\(.*\)own.version>.*</%<\1own.version>${newVersion}</>%" pom.xml > pom.xml.transformed
The pattern is a bit simplified, too, assuming that there is only one such version to be modified (i.e., it captures all old version numbers), and the closing tag identifier is omitted.
Since you told your Jenkins don't have xmlstarlet could you please try following awk and let me know then.
##Shell variable
new="1.8"
awk -v new_version="$new" '/own\.version/{sub(/>.*</,">"new_version"<")} 1' Input_file
Output will be as follows.
<properties>
<own.version>1.8</own.version>
</properties>
In case want to save output into Input_file itself append > temp_file && mv temp_file Input_file to above code then.

Print text value from xml using sed

using a one line sed command , how could i get the something and someone value?
<value name="something">someone</value>
Using the following regex <value name="(.*)">(.*)<\/value> i could retrieve the values with success using the site https://www.regex101.com/. But i'm not sure how could i do it using the command line.
Thanks in advance.
Something like
sed 's#.*name="\(.*\)">\(.*\)<.*#\1 \2#g'
Test
$ echo "<value name=\"something\">someone</value>" | sed 's#.*name="\(.*\)">\(.*\)<.*#\1 \2#g'
something someone
Try this.
sed -r 's/.*"(.*)">(.*)<.*>$/\1 \2/'
Noting the usual caveats about parsing XML with regular expressions, here's an XML parsing tool in action on your sample data that finds the attribute value and tag value for a "value" tag with a "name" attribute.
xmlstarlet sel -t -v '//value[#name]/#name' -n -v '//value[#name]' -n file.xml
something
someone

Get TagValue of nth occurence of a Tag in XML using sed

MY xml
<?xml version="1.0" encoding="UTF-8" ?>
<Attributes>
<Attribute>123</Attribute>
<Attribute>959595</Attribute>
<Attribute>1233</Attribute>
<Attribute>jiji</Attribute>
</Attributes>
I need to get the tag value of second occurence of attribute tag i.e 959595 using sed
i used the command
sed -n ':a;$!{N;ba};s#\(<Attribute\)\(.*\)\(</Attribute>\)#\1#2#\2#p' file
pattern one second occurrence pattern two value it doesnt work
i dont know whether my approach is correct or not please correct my command
The proper way to do this is :
$ xmllint --xpath '/Attributes/Attribute[2]/text()' file.xml
NOTES
xmllint comes with libxml2.
the '2' is the second searched element
sed -n '/<Attributes>/,\#</Attributes># {
/<Attribute>/ {
H;g
s#.*<Attribute>\(.*\)</Attribute>.*#\1#
t found
}
b
:found
p;q
}' YourFile
Assuming, like in your sample, there is only 1 Attributes to found, this sed only return the 1st. (if the xml content is only like your sample, the /<Attributes>/,\#</Attributes># selection is not needed)
Posix version so --posix on GNU sed
This sed prints all Attribute entries from the Attributes block, then takes the second entry and removes the tags:
sed -n '/<Attributes>/,\#</Attributes>#{/<Attribute>/p}' attrib.txt | sed -n '2p' | sed 's#</Attribute>##;s/<Attribute>//'
Output:
959595
Or another way without pipes is to use sed commands, this goes to the second entry strips the Attribute tag and then quits:
sed -n '/<Attributes>/,\#</Attributes>#{/<Attribute>/{n;s#.*<Attribute>\(.*\)</Attribute>.*#\1#;p;q};}' attrib.txt
Or if your number of Attribute entries changes you can make it a bit more intuitive by parsing all values and then using sed to print the attribute placement where you want:
sed -n '/<Attributes>/,\#</Attributes>#{/<Attribute>/{s#</Attribute>##;s#<Attribute>##;p}}' attrib.txt | sed -n '2p'
You can change the end where from 2, to whatever Attribute value field you want to display or take multiple values like sed -n '2p;3p' or sed -n '1,2p'
I also would follow the xmllint xpath way. It however seems like there is two versions available. According to this man page at https://linux.die.net/man/1/xmllint there is no xpath parameter, but it is called "pattern".
Following this documentation, your call then would be
$ xmllint --pattern '/Attributes/Attribute[2]/text()' file.xml
I recommend checking your local man page to see which one to use.