2017-11-21 19 views
1

次xmlstarletコマンド:私のファイルはdoc/ptxtを多く含んでいるため更新の.propertiesファイル

./xmlstarlet-1.5.0/xml.exe fo --dropdtd $filename | ./xmlstarlet-1.5.0/xml.exe sel -t -m "//DOC//PTXT" -v "concat(./@ID,' ', .)" 

は、複数の結果を返します。私は各出力で何かをする必要があります、より明示的に私は各ptxt値で何かをする必要があります。 XMLstarletのすべての結果をループするにはどうすればよいですか?私はid-valueペアを含む別のファイルを持っていると私はそれらのペアを一致させる必要があるため、

my.id.one Text I need 
my.id.two Text I also need 
my.id.three Surprisingly I need this text too 

と私は必要なのかもしれない二つの変数の各id-textペアを持つことであるidtext

私の出力は次のようになります。

アップデート1:

私は何をする必要があるかの具体的な例: 私はファイルX.xmlを持っているとY.properties ファイルX.xmlをファイルには、以下の構造を有する:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE DOC SYSTEM "ts.dtd"> 
<?xml-stylesheet type="text/css" href="ts.css"?> 
<DOC LOCALE="en-US"> 
    <PTXT ID="text.something">Open door</PTXT> 
    <PTXT ID="text.something.else">Open another door</PTXT> 
    <PTXT ID="text.whatever">Close all</PTXT> 
</DOC> 

ファイルY.propertiesがあり以下の構造:

text.something=Open window 
text.something.else=Open another door 

私が期待した結果が、この内容でY.propertiesです:行うには

text.something=Open door 
text.something.else=Open another door 
text.whatever=Close all 

  • value場合idからX.xmlにはY.propertieskeyからvalueと異なる、valuekeyからでY.propertiesを更新する必要があります。
  • X.xmlidからはY.propertieskeyからvalueと同じであるvalue場合X.xmlからidY.propertieskeyとして存在していない場合は、何も
  • に行われるべきではない、それはY.propertiesX.xmlからそのvalueを追加する必要があります

現在のシェルコードは、

です。

現在のところ、X.xmlからすべてのid/valueを取り出し、標準出力に出力します。 forはおそらく疑いがありますが、私はこのコードを実行するために複数のX.xmlY.propertiesがあるので、そこにあります。

問題1: @janos私は以下の問題があります。なぜ私は本当に理解できません。それはすべて正常に動作しますが、それらのほとんどはしません。例: XXML:

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE DOC SYSTEM "ts.dtd"> 
<?xml-stylesheet type="text/css" href="ts.css"?> 
<DOC> 
<PTXT ID="a.b.c.d" CONTEXT="label"><NTI>Text</NTI></PTXT> 
</DOC> 

Y.properties:

a.b.c.d=Text 

と私の出力は次のようになります。私は本当に何が起こっているのか理解していないよう

a.b.c.d= 
    Text= 
= 

は、あなたが私を助けてください。 out.properties

my.id=Öffnen Express WebTools 
my.id=\u00D6ffnen Express WebTools 

問題2: 次入力有する:で X.xmlを

my.id = \u00D6ffnen Express WebTools 

とY.properties

<PTXT ID="my.id" CONTEXT="">Öffnen <NTI>Express WebTools</NTI></PTXT> 

結果

代わり

my.id=Öffnen Express WebTools 
+0

サンプル入力と希望する出力を表示してください:https://stackoverflow.com/help/mcve –

+0

これは疑問の続きですhttps://stackoverflow.com/questions/47393839/extract-value-from-xml -in-shell/47393943?noredirect = 1#comment81775824_47393943。各出力項目をどのように処理すべきかを精緻化してください。 – RomanPerekhrest

+0

まあ、各出力は私にそのIDのテキストを与えてくれます。私は別のファイルでそのIDを検索して、そのテキストが正しいかどうかをチェックすることができます(正しいことを意味します)。 – Robert

答えて

1

の最初はY.propertiesでフォーマットに一致するデータを生成する:あなたたとえば

xmlstarlet fo --dropdtd a.xml | \ 
    xmlstarlet sel -t -m "//DOC//PTXT" -v $'concat(@ID, "=", ., "\n")' 

をこれが生成します。

text.something=Open door 
text.something.else=Open another door 
text.whatever=Close all 

その後、あなたは次のことを実行するためのAwkを使用することができますロジック:

  • セパレータとして=を使用して、キーと値のマップを構築し、ラインによってよう-
  • 使用Y.propertiesとして
  • プロセスラインを第二のファイルを最初のファイルを前のコマンドの出力を使用単純なロジックを使用して、キーがマップにない場合は、キーと値のペアを追加します。 xmlstarletの出力が最初に出力されるので、 上記のロジックはすべての値をマッピングに追加します。 2番目のファイル(Y.properties)の行を処理するので、既にキーがマップ内にある 行は無視されますが、 の新しいキーと値のペアが追加されます。このよう

xmlstarlet fo --dropdtd a.xml | \ 
    xmlstarlet sel -t -m "//DOC//PTXT" -v $'concat(@ID, "=", ., "\n")' | \ 
    awk -F= '!($1 in m) { m[$1] = $2 } 
      END { for (key in m) { print key "=" m[key] } }' - Y.properties 

あなたは所望の目標出力をファイルにリダイレクトすることができます。

上記のコードを複数のファイルに対して実行するには、 の関数で上記のコードを適切なパラメータでラップすることができます。 例:

mergeprops() { 
    local filename=$1 
    local propsfile=$2 
    local out=$3 

    xmlstarlet fo --dropdtd "$filename" | \ 
     xmlstarlet sel -t -m "//DOC//PTXT" -v $'concat(@ID, "=", ., "\n")' | \ 
     awk -F= '!($1 in m) { m[$1] = $2 } 
       END { for (key in m) { print key "=" m[key] } }' - "$propsfile" | sed 's/\s*=\s*/=/g' > "$out" 
} 

for filename in /c/Temp/XLocation/*.xml; do 
    mergeprops "$filename" Y.properties "$filename.out" 
done 

さらなるヘルプが必要な場合はお知らせください。

+0

あなたの解決策が私の最初の質問に答えるので、私は見つけた問題の別の質問を投稿しました。 https://stackoverflow.com/questions/47511395/update-properties-file-with-values-from-xml-file-problems – Robert

関連する問題