[BASH/SH/XML] Key / value pairs toevoegen aan XML file

Pagina: 1
Acties:

Vraag


Acties:
  • 0 Henk 'm!

  • TommyGun
  • Registratie: Mei 2004
  • Laatst online: 30-09 15:40

TommyGun

Stik er maar in!

Topicstarter
Beste mede Tweakers,

Op het moment heb ik de volgende XML file;

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<confluence-configuration>
  <setupStep>complete</setupStep>
  <setupType>custom</setupType>
  <buildNumber>8506</buildNumber>
  <properties>
    <property name="attachments.dir">${confluenceHome}/attachments</property>
    <property name="confluence.setup.server.id">BN4J-RBSE-6ZPZ-GB4G</property>
    <property name="confluence.webapp.context.path"></property>
    <property name="hibernate.connection.datasource">java:comp/env/jdbc/confluence</property>
    <property name="hibernate.database.lower_non_ascii_supported">true</property>
    <property name="hibernate.dialect">com.atlassian.confluence.impl.hibernate.dialect.PostgreSQLDialect</property>
    <property name="hibernate.setup">true</property>
    <property name="lucene.index.dir">${localHome}/index</property>
    <property name="synchrony.encryption.disabled">true</property>
    <property name="synchrony.proxy.enabled">true</property>
    <property name="webwork.multipart.saveDir">${localHome}/temp</property>
  </properties>
</confluence-configuration>


Nu wil ik daar diverse regels aan toevoegen. Dit gebeurt dmv een automatisch proces dus bij een volgende run moeten de regels geskipped dan wel geüpdatet worden.

code:
1
2
3
4
5
6
7
    <property name="hibernate.c3p0.acquire_increment">1</property>
    <property name="hibernate.c3p0.idle_test_period">100</property>
    <property name="hibernate.c3p0.max_size">60</property>
    <property name="hibernate.c3p0.max_statements">0</property>
    <property name="hibernate.c3p0.min_size">20</property>
    <property name="hibernate.c3p0.timeout">30</property>
    <property name="hibernate.c3p0.validate">true</property>


Ik probeer dit te bewerkstelligen met xmlstarlet maar de learning curve daarvan vind ik behoorlijk stijl.

Iemand die daarbij kan helpen alvorens ik terugval op andere methodes? (sed?).

Alvast bedankt! _/-\o_

“In a world without walls and fences, who needs Windows and Gates".

Beste antwoord (via TommyGun op 24-06-2021 19:03)


  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 02-10 16:57
Dat werkt inderdaad, maar kan dus ook zonder if door gebruik te maken van --delete, --append en --insert in één keer.

Voor de leuk kan je na de for loop ook de properties nog sorteren (tijdelijk bestand nodig omdat met xmlstarlet sel het bestand niet inplace gewijzigd kan worden):

code:
1
2
3
4
5
6
7
8
9
10
11
  for KEY in "${!xmlArray[@]}"; do    
    xmlstarlet ed --inplace \
      --delete "//property[@name='$KEY']" \
      --append "//properties/property[last()]" -t elem -n "property" -v "${xmlArray[$KEY]}" \
      --insert "//properties/property[last()]" -t attr -n name -v "$KEY" \
      ${CONFLUENCE_HOME}/confluence.cfg.xml
  done

  cp confluence.cfg.xml confluence.cfg.xml.tmp
  xmlstarlet sel --xml-decl --indent -t -m "/confluence-configuration" -e confluence-configuration -c "*[name()!='properties']" -e properties -m "properties/*" -s "A:T:U" "@name" -c . confluence.cfg.xml.tmp > confluence.cfg.xml
  rm confluence.cfg.xml.tmp

Alle reacties


Acties:
  • 0 Henk 'm!

  • OB1
  • Registratie: April 2014
  • Laatst online: 23:34

OB1

Met behulp van het `xml ed`-commando kun je in combinatie met een XPath-query rijen toevoegen, bijwerken, etc..

Zie ook de documentatie hier, specifiek hoofdstuk 3 Editing XML documents: http://xmlstar.sourceforge.net/doc/xmlstarlet.pdf

AMD 2700x @ 4.15 GHz | Vega 56 (Vega 64 BIOS) | 32 GB DDR4 | MSI X470 Gaming Plus | Intel 600P 1TB | Corsair RM550X


Acties:
  • 0 Henk 'm!

  • TommyGun
  • Registratie: Mei 2004
  • Laatst online: 30-09 15:40

TommyGun

Stik er maar in!

Topicstarter
OB1 schreef op donderdag 24 juni 2021 @ 11:20:
Met behulp van het `xml ed`-commando kun je in combinatie met een XPath-query rijen toevoegen, bijwerken, etc..

Zie ook de documentatie hier, specifiek hoofdstuk 3 Editing XML documents: http://xmlstar.sourceforge.net/doc/xmlstarlet.pdf
Ik wou net mijn post editen :)

Tot zover heb ik;

code:
1
xmlstarlet ed -s /confluence-configuration -t elem -n properties -v '' -d '/confluence-configuration/properties[position() != 1]' -s /confluence-configuration/properties -t elem -n 'property name' -v 'testje' confluence.cfg.xml


Wat resulteert in;
code:
1
    <property name>testje</property name>


Maar ik kom er niet in uit hoe ik het eerste en laatste deel tussen <> kan laten verschillen.

“In a world without walls and fences, who needs Windows and Gates".


Acties:
  • 0 Henk 'm!

  • downtime
  • Registratie: Januari 2000
  • Niet online

downtime

Everybody lies

TommyGun schreef op donderdag 24 juni 2021 @ 11:22:
[...]


Ik wou net mijn post editen :)

Tot zover heb ik;

code:
1
xmlstarlet ed -s /confluence-configuration -t elem -n properties -v '' -d '/confluence-configuration/properties[position() != 1]' -s /confluence-configuration/properties -t elem -n 'property name' -v 'testje' confluence.cfg.xml


Wat resulteert in;
code:
1
    <property name>testje</property name>


Maar ik kom er niet in uit hoe ik het eerste en laatste deel tussen <> kan laten verschillen.
Je element heet natuurlijk geen "property name". Het is element "property" met een attribuut wat "name" heet.

Acties:
  • 0 Henk 'm!

  • OB1
  • Registratie: April 2014
  • Laatst online: 23:34

OB1

Je zal op zoek moeten gaan naar attributes. Dat kan met het -a of --attr argument - als ik de documentatie mag geloven.

AMD 2700x @ 4.15 GHz | Vega 56 (Vega 64 BIOS) | 32 GB DDR4 | MSI X470 Gaming Plus | Intel 600P 1TB | Corsair RM550X


Acties:
  • 0 Henk 'm!

  • TommyGun
  • Registratie: Mei 2004
  • Laatst online: 30-09 15:40

TommyGun

Stik er maar in!

Topicstarter
Ben er al te lang naar aan het kijken denk ik, later nog maar een nieuwe poging wagen :F

“In a world without walls and fences, who needs Windows and Gates".


Acties:
  • 0 Henk 'm!

  • TommyGun
  • Registratie: Mei 2004
  • Laatst online: 30-09 15:40

TommyGun

Stik er maar in!

Topicstarter
Ik snap niet goed wat er gebeurt;

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<confluence-configuration>
  <setupStep>complete</setupStep>
  <setupType>custom</setupType>
  <buildNumber>8506</buildNumber>
  <properties>
    <property name="attachments.dir">${confluenceHome}/attachments</property>
    <property name="confluence.setup.server.id">BN4J-RBSE-6ZPZ-GB4G</property>
    <property name="confluence.webapp.context.path"></property>
    <property name="hibernate.connection.datasource">java:comp/env/jdbc/confluence</property>
    <property name="hibernate.database.lower_non_ascii_supported">true</property>
    <property name="hibernate.dialect">com.atlassian.confluence.impl.hibernate.dialect.PostgreSQLDialect</property>
    <property name="hibernate.setup">true</property>
    <property name="lucene.index.dir">${localHome}/index</property>
    <property name="synchrony.encryption.disabled">true</property>
    <property name="synchrony.proxy.enabled">true</property>
    <property name="webwork.multipart.saveDir">${localHome}/temp</property>
  </properties>
</confluence-configuration>


Als ik dan draai;
code:
1
xmlstarlet edit --update "/confluence-configuration/properties/property[@name='hibernate.c3p0.acquire_increment']/@name" --value "1" confluence.cfg.xml


Maakt 'ie er dit van;

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0" encoding="UTF-8"?>
<confluence-configuration>
  <setupStep>complete</setupStep>
  <setupType>custom</setupType>
  <buildNumber>8506</buildNumber>
  <properties>
    <property name="attachments.dir">${confluenceHome}/attachments</property>
    <property name="confluence.setup.server.id">BN4J-RBSE-6ZPZ-GB4G</property>
    <property name="confluence.webapp.context.path"/>
    <property name="hibernate.connection.datasource">java:comp/env/jdbc/confluence</property>
    <property name="hibernate.database.lower_non_ascii_supported">true</property>
    <property name="hibernate.dialect">com.atlassian.confluence.impl.hibernate.dialect.PostgreSQLDialect</property>
    <property name="hibernate.setup">true</property>
    <property name="lucene.index.dir">${localHome}/index</property>
    <property name="synchrony.encryption.disabled">true</property>
    <property name="synchrony.proxy.enabled">true</property>
    <property name="webwork.multipart.saveDir">${localHome}/temp</property>
  </properties>
</confluence-configuration>


Waarom 'verpest' ie de 3e property (confluence.webapp.context.path) en gebeurt er verder niets :? 8)7 |:(

“In a world without walls and fences, who needs Windows and Gates".


Acties:
  • 0 Henk 'm!

  • ThomasG
  • Registratie: Juni 2006
  • Laatst online: 23-09 14:00
TommyGun schreef op donderdag 24 juni 2021 @ 15:05:
*knip*

Waarom 'verpest' ie de 3e property (confluence.webapp.context.path) en gebeurt er verder niets :? 8)7 |:(
Hij wordt niet verpest, maar herschreven naar self-closing element omdat de body leeg is. Daarnaast geeft je aan dat je <property name="hibernate.c3p0.acquire_increment"/> wilt updaten, maar die komt niet voor in jouw XML. Dus gebeurt er niets, want er is niets te updaten.

Acties:
  • 0 Henk 'm!

  • TommyGun
  • Registratie: Mei 2004
  • Laatst online: 30-09 15:40

TommyGun

Stik er maar in!

Topicstarter
ThomasG schreef op donderdag 24 juni 2021 @ 15:28:
[...]
Hij wordt niet verpest, maar herschreven naar self-closing element omdat de body leeg is. Daarnaast geeft je aan dat je <property name="hibernate.c3p0.acquire_increment"/> wilt updaten, maar die komt niet voor in jouw XML. Dus gebeurt er niets, want er is niets te updaten.
Ah, zie nu pas dat 'ie leeg is. Normaal zou daar een / in moeten staan, maar 'leeg' of '/' maakt blijkbaar voor de applicatie niet uit. Al heb ik heb geen idee of "<property name="confluence.webapp.context.path"/>" (voor de applicatie) hetzelfde geïnterpreteerd wordt.

Anyhow, --insert verwacht andere opties dan --update, hoe kan ik dat het beste oplossen? Ik wil de values bijwerken indien aanwezig en anders toevoegen.

EDIT: ok, het updaten lukt met;

code:
1
xmlstarlet ed --update "/confluence-configuration/properties/property[@name='hibernate.c3p0.acquire_increment']" --value "5" confluence.cfg.xml


Nu verder prutsen met de insert :) Prima als dat 2 commando's worden, dat los ik elders wel op.

[ Voor 15% gewijzigd door TommyGun op 24-06-2021 15:45 ]

“In a world without walls and fences, who needs Windows and Gates".


Acties:
  • 0 Henk 'm!

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 02-10 16:57
Even terzijde, die properties zullen niet veel uitmaken omdat je een JNDI datasource gebruikt. In Tomcat worden die al met een connection pool (DBCP) gemanaged qua max connecties. Dus zul je alleen in /conf/server.xml de waarde van het attribuut maxTotal moeten aanpassen. Zie de Confluence docs.

Als je een property als deze al bestaat wil updaten of toevoegen als deze nog niet bestaat kan dat door deze eerst te verwijderen en dan weer toe te voegen. Dat kan met een xmlstarlet one-liner, omdat je meerdere acties kan doen:

code:
1
xmlstarlet ed --delete "//property[@name='hibernate.c3p0.acquire_increment']" --append "//properties/property[last()]" -t elem -n "property" -v "15" --insert "//properties/property[last()]" -t attr -n name -v "hibernate.c3p0.acquire_increment" confluence.cfg.xml

(de property komt hiermee wel altijd op het einde te staan, ook al stond de property al ergens midden in de lijst)

[ Voor 5% gewijzigd door matthijsln op 24-06-2021 17:31 ]


Acties:
  • 0 Henk 'm!

  • TommyGun
  • Registratie: Mei 2004
  • Laatst online: 30-09 15:40

TommyGun

Stik er maar in!

Topicstarter
matthijsln schreef op donderdag 24 juni 2021 @ 17:26:
Even terzijde, die properties zullen niet veel uitmaken omdat je een JNDI datasource gebruikt. In Tomcat worden die al met een connection pool (DBCP) gemanaged qua max connecties. Dus zul je alleen in /conf/server.xml de waarde van het attribuut maxTotal moeten aanpassen. Zie de Confluence docs.

Als je een property als deze al bestaat wil updaten of toevoegen als deze nog niet bestaat kan dat door deze eerst te verwijderen en dan weer toe te voegen. Dat kan met een xmlstarlet one-liner, omdat je meerdere acties kan doen:

code:
1
xmlstarlet ed --delete "//property[@name='hibernate.c3p0.acquire_increment']" --append "//properties/property[last()]" -t elem -n "property" -v "15" --insert "//properties/property[last()]" -t attr -n name -v "hibernate.c3p0.acquire_increment" confluence.cfg.xml

(de property komt hiermee wel altijd op het einde te staan, ook al stond de property al ergens midden in de lijst)
1 van de redenen dat ik hier mee bezig ben is de overstap van JNDI naar C3P0 :)

Ik heb nu het volgende, wat lijkt te werken. Niet helemaal tevreden mee maar ik zie door de bomen het bos niet meer :+

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
  declare -A xmlArray
  xmlArray[hibernate.c3p0.acquire_increment]=1
  xmlArray[hibernate.c3p0.idle_test_period]=100
  xmlArray[hibernate.c3p0.max_size]=${CONFLUENCE_MAX_DB_CONNECTIONS}
  xmlArray[hibernate.c3p0.max_statements]=0
  xmlArray[hibernate.c3p0.min_size]=20
  xmlArray[hibernate.c3p0.timeout]=30
  xmlArray[hibernate.c3p0.validate]=true
  xmlArray[hibernate.connection.driver_class]=org.postgresql.Driver
  xmlArray[hibernate.connection.isolation]=2
  xmlArray[hibernate.connection.password]=${CONFLUENCE_DATABASE_PASSWORD}
  xmlArray[hibernate.connection.url]=${CONFLUENCE_DATABASE_URL}
  xmlArray[hibernate.connection.username]=${CONFLUENCE_DATABASE_USERNAME}

  xmlstarlet ed --inplace -d "/confluence-configuration/properties/property[@name='hibernate.connection.datasource']" ${CONFLUENCE_HOME}/confluence.cfg.xml

  for KEY in "${!xmlArray[@]}"; do
    if [ -n "$(xmlstarlet sel -T -t -v "/confluence-configuration/properties/property[@name='$KEY']/@name" ${CONFLUENCE_HOME}/confluence.cfg.xml)" ]; then
      xmlstarlet ed --inplace --update "/confluence-configuration/properties/property[@name='$KEY']" --value "${xmlArray[$KEY]}" ${CONFLUENCE_HOME}/confluence.cfg.xml;
    else
      xmlstarlet edit -L --subnode "/confluence-configuration/properties" --type elem -n property --value "${xmlArray[$KEY]}" --insert "/confluence-configuration/properties/property[last()]" --type attr -n name --value "$KEY" ${CONFLUENCE_HOME}/confluence.cfg.xml;
    fi
  done

“In a world without walls and fences, who needs Windows and Gates".


Acties:
  • Beste antwoord
  • +1 Henk 'm!

  • matthijsln
  • Registratie: Augustus 2002
  • Laatst online: 02-10 16:57
Dat werkt inderdaad, maar kan dus ook zonder if door gebruik te maken van --delete, --append en --insert in één keer.

Voor de leuk kan je na de for loop ook de properties nog sorteren (tijdelijk bestand nodig omdat met xmlstarlet sel het bestand niet inplace gewijzigd kan worden):

code:
1
2
3
4
5
6
7
8
9
10
11
  for KEY in "${!xmlArray[@]}"; do    
    xmlstarlet ed --inplace \
      --delete "//property[@name='$KEY']" \
      --append "//properties/property[last()]" -t elem -n "property" -v "${xmlArray[$KEY]}" \
      --insert "//properties/property[last()]" -t attr -n name -v "$KEY" \
      ${CONFLUENCE_HOME}/confluence.cfg.xml
  done

  cp confluence.cfg.xml confluence.cfg.xml.tmp
  xmlstarlet sel --xml-decl --indent -t -m "/confluence-configuration" -e confluence-configuration -c "*[name()!='properties']" -e properties -m "properties/*" -s "A:T:U" "@name" -c . confluence.cfg.xml.tmp > confluence.cfg.xml
  rm confluence.cfg.xml.tmp

Acties:
  • 0 Henk 'm!

  • TommyGun
  • Registratie: Mei 2004
  • Laatst online: 30-09 15:40

TommyGun

Stik er maar in!

Topicstarter
Bedankt voor de input allen :)

“In a world without walls and fences, who needs Windows and Gates".

Pagina: 1