Manipulowanie wierszem poleceń XML (skrypt powłoki)


9

Jak manipulować XML z wiersza poleceń w skrypcie powłoki?

Istnieje wiele poleceń do manipulowania danymi tabelarycznymi, zastępowania zmiennych środowiskowych lub zastępowania fragmentów tekstu wyrażeniami regularnymi, ale nic nie znalazłem dla XML.

Mój skrypt kompilacji musi wstawić znacznik z zawartością w głównym znaczniku dokumentu xml i uważam, że przesadzenie polega na zainstalowaniu java, perl lub python w OS w tym celu (moje skrypty są wykonywane w gitlab z obrazami dokerów, więc robię to moja praca z narzędziami dostępnymi w maven: obraz 3,5-jdk-8 byłaby snem).

Nie chcę manipulować XML za pomocą sed, chociaż w moim skrypcie kompilacji to działałoby, ponieważ jest złe .

Przykład: Mam następujący plik 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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>  
  <!-- a lot of other tags-->
</project>  

I chcę wstawić następujący blok:

<distributionManagement>
    <repository>
        <id>private-releases</id>
        <url>https://my.private.server.com/nexus/repository/maven-releases/</url>
    </repository>
</distributionManagement>

wewnątrz tagu projektu (i nie ma w pełni znaczenia, czy będzie na początku, czy na końcu).


opublikuj swój wkład xml i oczekiwany wynik
RomanPerekhrest

Czyli szczegółowe wymagania dotyczą parsera XML, który można wywołać z wiersza poleceń, który nie jest zaimplementowany w żadnym z głównych języków skryptowych, ale jako wolnostojące narzędzie C lub C ++ (lub inne skompilowane)?
Kusalananda

@Kusalanda Podałem, że uruchamiam skrypty w kontenerach dokerów, więc najważniejsze jest dla mnie, aby dodać jak najmniej do obrazu dokera.
9ilsdx 9rvj 0lo

Jeśli masz obraz z maven i jdk, to Java wydaje mi się najlepszą opcją dla mnie .... dlaczego w takim przypadku uważasz Java za ciężką?
Daniel Pryden,

Prawdopodobnie warto zadać to pytanie na temat przepełnienia stosu i otagować za pomocą maven- Podejrzewam, że jest lepszy sposób na robienie tego, co próbujesz zrobić w samym Maven.
Daniel Pryden

Odpowiedzi:


10

XMLStarlet ( http://xmlstar.sourceforge.net/overview.php ) jest napisany w C i używa libxml2i libxslt.

Biorąc pod uwagę dokument XML

<?xml version="1.0"?>
<root>
  <tag>data</tag>
</root>

podwęzeł, do którego rootmożna wstawić, używając

xml ed -s '/root' -t elem -n 'newtag' -v 'newdata' file.xml

który produkuje

<?xml version="1.0"?>
<root>
  <tag>data</tag>
  <newtag>newdata</newtag>
</root>

Wstawianie wielu rzeczy (używając oryginału file.xmlu góry tutaj):

xml ed -s '/root' -t elem -n 'newtag' \
       -s '/root/newtag' -t elem -n 'subtag' -v 'subdata' file.xml

To produkuje

<?xml version="1.0"?>
<root>
  <tag>data</tag>
  <newtag>
    <subtag>subdata</subtag>
  </newtag>
</root>

Na przykład w pytaniu:

xml ed -N x="http://maven.apache.org/POM/4.0.0" \
       -s '/x:project' -t elem -n 'distributionManagement' \
       -s '/x:project/distributionManagement' -t elem -n 'repository' \
       -s '/x:project/distributionManagement/repository' -t elem -n 'id' \
         -v 'private-releases' \
       -s '/x:project/distributionManagement/repository' -t elem -n 'url' \
         -v 'https://my.private.server.com/nexus/repository/maven-releases/' \
    file.xml

Wynik:

<?xml version="1.0"?>
<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <!-- a lot of other tags-->
  <distributionManagement>
    <repository>
      <id>private-releases</id>
      <url>https://my.private.server.com/nexus/repository/maven-releases/</url>
    </repository>
  </distributionManagement>
</project>

Wstawianie wcześniej przygotowanego pliku XML w lokalizacji w pliku XML:

Zakładając, że oryginalny kod XML z pytania jest w, file.xmla dodatkowe bity, które powinny przejść w nowym distributinManagementwęźle, znajdują się w new.xml(ale nie w samym znaczniku węzła), można wykonać następujące czynności, aby wstawić new.xmldo węzła głównego:

xml ed -N x="http://maven.apache.org/POM/4.0.0" \
       -s '/x:project' -t elem -n 'distributionManagement' \
       -v "$(<new.xml)" file.xml | xml unesc | xml fo

XMLStarlet automatycznie usunie dane, które wymagają zmiany znaczenia, takie jak <i >znaki. xml unescNieco unescapes wstawione dane (faktycznie unescapes cały dokument, który może lub nie może być problemem) i xml foformatuje wynikowego dokumentu XML.

Wynik to

<?xml version="1.0"?>
<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>
  <!-- a lot of other tags-->
  <distributionManagement>
    <repository>
      <id>private-releases</id>
      <url>https://my.private.server.com/nexus/repository/maven-releases/</url>
    </repository>
  </distributionManagement>
</project>

Jestem trochę zaniepokojony robieniem tego w ten sposób, „ale to działa”.

Zobacz także podobne pytanie dotyczące StackOverflow: /programming/29298507/xmlstarlet-xinclude-xslt


Wygląda interesująco, chociaż przy wstawianiu więcej niż jednego pojedynczego znacznika składnia jest dość długa. Tyle tylko, że w Ubuntu nosi nazwę „xmlstarlet”. Czy można wstawić zawartość innego pliku jako znacznik, zakładając, że zawartość jest prawidłowym plikiem XML?
9ilsdx 9rvj 0lo

@ 9ilsdx9rvj0lo Zobacz zaktualizowaną odpowiedź.
Kusalananda

„w rzeczywistości odsłania cały dokument, co może, ale nie musi stanowić problemu”. Tak, ogromny problem, wszystkie istniejące & amp; zostały zakodowane, co spowodowało, że XML przestał być ważny :(
rob

1

Uważam, że instalowanie w tym celu java, perl lub python w OS jest przesadą (moje skrypty są wykonywane w gitlab z obrazami dokerów, więc wykonywanie mojej pracy za pomocą narzędzi dostępnych w maven: obraz 3.5-jdk-8 byłoby snem).

prawdopodobnie nadal jest to przesada, ale jeśli martwisz się tylko pojemnikiem, możesz użyć bardzo lekkiego języka, takiego jak Lua lub Guile.

z dokumentów Lua:

Dodanie Lua do aplikacji nie powoduje wzdęcia. Plik archiwum dla Lua 5.3.4, który zawiera kod źródłowy i dokumentację, wymaga skompresowania 297K i nieskompresowania 1,1M. Źródło zawiera około 24000 linii C. Pod 64-bitowym Linuksem interpreter Lua zbudowany ze wszystkimi standardowymi bibliotekami Lua zajmuje 246 KB, a biblioteka Lua 421 KB.


Warto rozważyć dodanie LUA do pojemnika maven, dzięki za wskazówkę.
9ilsdx 9rvj 0lo
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.