XMLStartlet is not updating package.xml file - xml-namespaces

I want to create Salesforce Dynamic package.xml file. I followed the process mentioned in this (apexandbeyond.wordpress.com/2017/03/15/dynamic-package-xml-generation/) blog, it is neither updating not inserting dat in xml file. I am trying following way but i doesn't work for me. please help me on this.
xmlstarlet edit -L --subnode "/Package/types[name='ApexClass']" --type elem -n members -v "LoginBroker" testpackage.xml > edipackage.xml
xmlstarlet edit --insert /Package -t attr -n xmlns -v "http://soap.sforce.com/2006/04/metadata" testpackage.xml > edipackage.xml
Original file: testpackage.xml
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>*</members>
<name>ApexClass</name>
</types>
<types>
<members>*</members>
<name>ApexComponent</name>
</types>
<types>
<members>*</members>
<name>ApexPage</name>
</types>
<version>48.0</version>
</Package>
Expected result:
<Package xmlns="http://soap.sforce.com/2006/04/metadata">
<types>
<members>LoginBroker</members>
<name>ApexClass</name>
</types>
<types>
<version>48.0</version>
</Package>

If I understand you correctly, you are looking for something like this:
xmlstarlet edit -N x="http://soap.sforce.com/2006/04/metadata"\
-u "//x:Package//x:types[x:name[1][text()='ApexClass']]/x:members" \
-v 'LoginBroker' \
testpackage.xml > edipackage.xml

Related

updating xml, using xmlstarlet, with a sequence of letters

When I am having input.xml, and want to update it to get output.xml (see below) XMLSTARLET fails.
First I tried to find the correct XSLT function to get the needed values, which led to this:
xmlstarlet sel -t -m //field -v . -o "=" -v 'substring("ABCDEFGHIJK",position(),1)' -n input.xml
output:
5 =A
3 =B
2 =C
4 =D
55 =E
42 =F
This made me believe that I should be able to update this XML with the following command:
xmlstarlet ed -u //field -x 'substring("ABCDEFGHIJK",position(),1)' input.xmlxmlstarlet ed -u //field -x 'substring("ABCDEFGHIJK",position(),1)' input.xml
But I did get:
Invalid context position
Segmentation fault
I tried using XmlStarlet on Windows 11, and on Ubuntu 20.04, both did a core dump.
I am interested in another solution using XmlStarlet.
FILES
input.xml
<root>
<field> 5 </field>
<field> 3 </field>
<field> 2 </field>
<field> 4 </field>
<field> 55 </field>
<field> 42 </field>
</root>
(desired) output.xml
<root>
<field>A</field>
<field>B</field>
<field>C</field>
<field>D</field>
<field>E</field>
<field>F</field>
</root>
position() works with xmlstarlet select's -m (--match) option (i.e. xsl:for-each) which determines the context position.
xmlstarlet select --indent -t \
-e '{name(*)}' \
-m '//field' -e '{name()}' -v 'substring("ABCDEFGHIJK",position(),1)' \
file.xml
With xmlstarlet edit's -u (--update) you can use a sibling node count, e.g.
xmlstarlet edit -O \
-u '//field' -x 'substring("ABCDEFGHIJK",1+count(preceding-sibling::field),1)' \
file.xml
or
xmlstarlet edit -O \
-u '//field' -x 'substring("ABCDEFGHIJK",count(preceding-sibling::* | self::*),1)' \
file.xml
Each of these commands produces the desired output. Line continuation chars added for readability.

CAT EOF generated in a single line fail to run

I have a yaml file where I want to write a XML:
script:
- >
cat > settings.xml << EOF
<?xml version="1.0" encoding="UTF-8"?>
<settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" xmlns="http://maven.apache.org/SETTINGS/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<servers>
<server>
<username>$USERNAME</username>
<password>$PASSWORD</password>
<id>central</id>
</server>
</servers>
</settings>
EOF
If I run the cat command in my terminal, it works but when it's executed by my pipeline, this command become a single line failing:
cat > settings.xml << EOF <?xml version="1.0" encoding="UTF-8"?> <settings xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd" xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <servers> <server> <username>$USER</username> <password>$PASSWORD</password> <id>central</id> </server> </servers> </settings> EOF
With the error:
parse error near `<'
Any idea how to fix this error or generate a well formated XML?
There are two problems:
Incorrect syntax (incorrect cat > settings.xml << EOF instead of correct cat << EOF > settings.xml)
The end-string EOF must be at the beginning of the line but it isn't.
To run this from the command line:
Type cat << EOF > settings.xml and press ENTER.
Paste (or type by hand) your XML document (without the end-string EOF) and press ENTER.
Type EOF (make sure it is at the beginning of the line!) and press ENTER.
You will be presented with the command prompt. Type ls -l settings.xml to see the newly created file.
To run this from a script:
Open your text editor and follow the steps 1, 2 and 3.
Save it under the name, lets say script.sh and make it executable:
chmod 755 script.sh
Run it:
./script.sh
When the command promt is back, type ls -l settings.xml, to see the newly created file.

find a specific groupId from a maven pom.xml using xmstarlet

I'm trying to find a specific groupId and artifactId from a Maven POM.XML using xmlstarlet without success.
This is the command that I'm using:
xmlstarlet sel -N pom=http://maven.apache.org/POM/4.0.0 -t \
-m "/pom:project/pom:dependencyManagement/pom:dependencies/pom:dependency[.//pom:groupId=com.mygroup.xxx]" \
-v '.' pom.xml
any Help is appreciated.
EDIT: Thank to npostavs, for other people who have the same question, It is also possible to combine more expressions and filter the result based on more elements:
xmlstarlet sel -N pom=http://maven.apache.org/POM/4.0.0 -t -m "/pom:project/pom:dependencyManagement/pom:dependencies/dependency[.//pom:groupId='com.mygroup.xxx'][.//pom:artifactId='myartifact-xxx']" -v '.' pom.xml
pom:groupId=com.mygroup.xxx
You need quotes around string literals: pom:groupId='com.mygroup.xxx', otherwise it looks for XML elements named com.mygroup.xxx.

Unable to get version using artifactId from pom file

I am fairly new to unix shell scripting. Trying to capture version info of some artifact from xpom.xml without success.
I can't install anything extra in the system, checked that xmllint is installed.
Any solution using either direct unix command or xmllint is appreciated.
file =~/xpom.xml
<project xmlns=http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.generic</groupId>
<artifactId>genericlist</artifactId>
<packaging>pom</packaging>
<version>10.0.25</version>
<name>GenericRelease12.x.3</name>
<description>GenericRelRepo</description>
<dependencies>
<dependency>
<groupId>org.alpha</groupId>
<artifactId>alpha</artifactId>
<version>1.1.1</version>
<type>war</type>
</dependency>
<dependency>
<groupId>com.db</groupId>
<artifactId>oradatabase</artifactId>
<version>7.7.7</version>
<type>jar</type>
</dependency>
</dependencies>
</project>
I need to capture version of oradatabase artifactId. Solution should return 7.7.7.
I tried following without any success (got these tips from this site and modified it to meet my need:
attempt 1:
xmllint --xpath '//project/dependencies/dependency[artifactId='oradatabase']/#value' xpom.xml
it throws Unknown option --xpath
attempt 2:
artifactId=$(xmllint --format --shell "$file" <<< "cat //project/dependencies/dependency/artifactId/text()" | grep -v /)
if [[ $artifactId =~ ^(oradatabase)$ ]]
then
version=$(xmllint --format --shell "$file" <<< "cat //project/dependencies/dependency/artifactId/text()" | grep -v /)
echo "version is: " ${version}
else
echo "Not found"
fi
-- returns Not found.
Thanks for any help on this.
You can try this:
grep -A 1 oradatabase pom.xml | sed -nr 's|.*<version>(.*)</version>.*|\1|p'
grep -A 1 oradatabase finds the line with oradatabase and prints also one line after it (context after).
Then sed simply extracts the version number.

xmlstarlet - need to selectively replace attribute value based on value of another attribute

Just wondering if anyone can help me.
I'm currently building a pfsense firewall, which uses VPN connections to secure the traffic.
The VPN provider does provide a port forwarding mechanism, but the incoming port number changes every hour. I have a script which allows me to discover the new port, but I need a scripted way to modify the port forward settings in the firewall to match.
A snippet of the firewall config file that controls this is as follows:
<?xml version="1.0"?>
<pfsense>
<nat>
<rule>
<source>
<any/>
</source>
<destination>
<any/>
<port>53400</port>
</destination>
<protocol>tcp/udp</protocol>
<target>192.168.0.15</target>
<local-port>53400</local-port>
<interface>opt2</interface>
<descr><![CDATA[Torrent]]></descr>
<associated-rule-id>nat_52d81d2dc904f5.77023355</associated-rule-id>
<created>
<time>1389894957</time>
<username>admin#192.168.0.20</username>
</created>
<updated>
<time>1389980696</time>
<username>admin#192.168.0.20</username>
</updated>
</rule>
</nat>
<filter>
<rule>
<id/>
<type>pass</type>
<interface>opt2</interface>
<ipprotocol>inet</ipprotocol>
<tag/>
<tagged/>
<max/>
<max-src-nodes/>
<max-src-conn/>
<max-src-states/>
<statetimeout/>
<statetype>keep state</statetype>
<os/>
<protocol>tcp/udp</protocol>
<source>
<any/>
</source>
<destination>
<address>192.168.0.15</address>
<port>53400</port>
</destination>
<log/>
<descr><![CDATA[NAT Torrent]]></descr>
<associated-rule-id>nat_52d81d2dc904f5.77023355</associated-rule-id>
<created>
<time>1389894957</time>
<username>NAT Port Forward</username>
</created>
<updated>
<time>1389899075</time>
<username>admin#192.168.0.20</username>
</updated>
</rule>
</filter>
</pfsense>
In the XML above, we have the two parts which comprise a port forward rule for pfsense. The part enclosed in the <nat> section is the port forward. The section in the <rule> is an interface specific incoming firewall rule. Both have to be modified for the new port forward setting to be effective.
I was thinking to use xmlstarlet to modify the config file, using the <descr> as my key for identifying which sections to change.
I'm aware that you can have data like:
<username><![CDATA[name]]></username>
<password><![CDATA[password]]></password>
<dbname><![CDATA[name]]></dbname>
and modify it with:
xml ed -P -O -L \
-u '//username/text()' -v 'something' \
-u '//password/text()' -v 'somethingelse' \
-u '//dbname/text()' -v 'somethingdifferent' file.xml
and also that you can have something like:
<objects>
<object>
<name>Foo</name>
<constant1>10</constant1>
<constant2>20</constant2>
</object>
<object>
<name>Bar</name>
<constant1>15</constant1>
<constant2>40</constant2>
</object>
<objects>
and update attributes with:
xmlstarlet ed -u '//object[name="Foo"]/const1' -v 18 sample.xml
However, I'm struggling to merge the two, so that I have a single statement which matches <descr>="Torrent" and then updates the relevant <port> and <local-port> attributes.
Any help with a suitable xmlstarlet command would be much appreciated.
xmlstarlet ed \
-u '//rule[descr="Torrent"]/destination/port' -v 1111 \
-u '//rule[descr="Torrent"]/local-port' -v 2222 \
sample.xml

Resources