XMLコマンドライン(シェルスクリプト)の操作


9

シェルスクリプトのコマンドラインからXMLを操作する方法

表形式のデータを操作したり、環境変数を置き換えたり、テキストフラグメントを正規表現に置き換えたりするためのコマンドはたくさんありますが、XMLについては何も見つかりませんでした。

私のビルドスクリプトは、xmlドキュメントのメインタグ内にコンテンツを含むタグを挿入する必要があり、その目的でOSにjava、perl、またはpythonをインストールするのはやり過ぎです(私のスクリプトは、Dockerイメージを使用してgitlabで行われるため、 maven:3.5-jdk-8画像で利用できるツールでの私の仕事は夢でしょう)。

私のビルドスクリプトで、それが仕事だろうが、それはだから、私は、sedを持つXMLを操作したくない

例:次の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>  

そして、私は次のブロックを挿入したいと思います:

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

プロジェクトタグの内部(そして、それが最初にあるか最後にあるかは完全に問題ではありません。


入力xmlと予想される出力を投稿する
RomanPerekhrest

したがって、特定の要件は、主要なスクリプト言語のいずれにも実装されていないが、独立したCまたはC ++(またはその他のコンパイル済み)ユーティリティであるコマンドラインから呼び出すことができるXMLパーサーに対するものですか?
クサラナンダ

@Kusalanda私はDockerコンテナー内でsciptsを実行していることを指定したので、Dockerイメージにできるだけ追加しないことが最も重要です。
9ilsdx 9rvj 0lo 2018

mavenとjdkのイメージがある場合、Javaは私にとって最良のオプションのように聞こえます。この場合、なぜJavaをヘビー級と見なすのですか?
Daniel Pryden

Stack Overflowでこの質問をしてタグ付けするのはおそらく価値mavenがあります-Maven自体の内部で実行しようとしていることを行うためのより良い方法があると思います。
Daniel Pryden

回答:


10

XMLStarlet(http://xmlstar.sourceforge.net/overview.php)はCで書かれており、およびを使用libxml2libxsltます。

XMLドキュメントを考える

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

rootを使用して挿入されるサブノード

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

生成する

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

多くのものを挿入する(file.xmlここの上部にあるオリジナルを使用):

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

これにより

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

質問の例では:

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

結果:

<?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>

以前に準備したXMLファイルをXML内の場所に挿入します。

質問の元のXMLがありfile.xml、新しいdistributinManagementノードに追加する必要がある追加のビットが含まれているnew.xml(ただし、ノードタグ自体は含まれていない)場合、次のようnew.xmlしてルートノードに挿入できます。

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は自動的にエスケープする必要のあるデータ、などのエスケープされます<>文字が。このxml unescビットは、挿入されたデータのエスケープを解除し(実際にはドキュメント全体のエスケープを解除します。これは問題となる場合とそうでない場合があります)、xml fo結果のXMLドキュメントを再フォーマットします。

結果は

<?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>

私はこのようにそれをすることについて少し不安です、しかし「それはうまくいきます」。

StackOverflowでこの関連質問も参照してください:https : //stackoverflow.com/questions/29298507/xmlstarlet-xinclude-xslt


興味深いのですが、複数の単一タグを挿入する場合、構文はかなり長くなります。ubuntuではそれだけが「xmlstarlet」という名前です。コンテンツが有効なxmlであると仮定して、他のファイルのコンテンツをタグとして挿入することは可能ですか?
9ilsdx 9rvj 0lo 2018

@ 9ilsdx9rvj0lo更新された回答を参照してください。
クサラナンダ

「それは実際にドキュメント全体のエスケープを解除します、それは問題かもしれないし、そうでないかもしれません」。うん大規模な問題、すべての既存の&amp; エンコードされていないため、XMLは無効になります:(
rob

1

その目的のためにOSにjava、perl、またはpythonをインストールするのはやり過ぎです(私のスクリプトはDoclabイメージを使用してgitlabで行われるため、maven:3.5-jdk-8イメージで利用可能なツールを使用して私の仕事をするのは夢でしょう)。

それはおそらくやり過ぎですが、コンテナのサイズだけに関心がある場合は、LuaやGuileなどの非常に軽量な言語を使用できます。

Luaのドキュメントから:

Luaをアプリケーションに追加しても、肥大化することはありません。Lua 5.3.4のtarballには、ソースコードとドキュメントが含まれており、圧縮された297Kと圧縮されていない1.1Mです。ソースには約24000行のCが含まれています。64ビットLinuxでは、すべての標準Luaライブラリで構築されたLuaインタープリターは246K、Luaライブラリは421Kかかります。


ヒントをありがとう、単にLUAをmavenコンテナーに追加することを検討する価値があります。
9ilsdx 9rvj 0lo 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.