0

これがサンプルファイルで、値を区切り記号形式のファイルに変換する必要があります:-

test.xml

<?xml version="1.0" encoding="UTF-8" ?>
 <testjar>

 <testable>
 <trigger>Trigger1</trigger>
 <message>2012-06-14T00:03.54</message>
 <sales-info>
 <san-a>no</san-a>
 <san-b>no</san-b>
 <san-c>no</san-c>
 </sales-info>
 </testable>


  <testable>
  <trigger>Trigger2</trigger>
  <message>2012-06-15T00:03.54</message>
  <sales-info>
  <san-a>yes</san-a>
  <san-b>yes</san-b>
  <san-c>no</san-c>
  </sales-info>
 </testable>

 </testjar>

各レコードは新しい行で開始する必要があります。サンプルの結果セットは、次の sample.txt のようになります。

Trigger1|2012-06-14T00:03.54|no|no|no  
Trigger2|2012-06-15T00:03.54|yes|yes|no

注:- xmlstarlet がサーバーにインストールされていません。xmlstarlet なしでこれを実行できますか?

4

3 に答える 3

1

xmlstarletがインストールされている場合は、次のことを試すことができます。

me@home$ xmlstarlet sel -t -m "//testable" -v trigger -o "|" -v message -o "|" -m sales-info -v san-a -o "|" -v san-b -o "|" -v san-c -n test.xml
Trigger1|2012-06-14T00:03.54|no|no|no
Trigger2|2012-06-15T00:03.54|yes|yes|no

コマンドの内訳:

xmlstarlet sel -t 
    -m "//testable"       # match <testable>
      -v trigger -o "|"     # print out value of <trigger> followed by |
      -v message -o "|"     # print out value of <message> followed by | 
      -m sales-info         # match <sales-info>
        -v san-a -o "|"       # print out value of <san-a> followed by |
        -v san-b -o "|"       # print out value of <san-b> followed by | 
        -v san-c              # print out value of <san-c>
    -n                   # print new line
    test.xml             # INPUT XML FILE

内で変化するタグをターゲットにするに<testable>は、すべてのリーフノードのテキストを返す次のことを試してください。

ma@home$ xmlstarlet sel -t -m "//testable" -m "descendant::*[not(*)]" -v 'text()' -i 'not(position()=last())' -o '|' -b -b -n test.xml 
Trigger1|2012-06-14T00:03.54|no|no|no
Trigger2|2012-06-15T00:03.54|yes|yes|no

コマンドのビークダウン:

xmlstarlet sel -t 
    -m "//testable"                         # match <testable>
      -m "descendant::*[not(*)]"              # match all leaf nodes
        -v 'text()'                             # print text
        -i 'not(position()=last())' -o '|'      # print | if not last item
        -b -b                                   # break out of nested matches
    -n                                      # print new line
    test.xml                                # INPUT XML FILE

にアクセスできない場合はxmlstarlet、他に自由に使用できるツールを調べてください。他のオプションには、xsltproc(mzjnの回答を参照)とxpathが含まれます。

これらのツールが利用できない場合は、適切なXMLライブラリにアクセスできる高級言語(Python、Perl)を使用することをお勧めします。

を使用して手動で解析することは可能ですが、特に入力に一貫性regexがない場合、このようなソリューションは理想的ではありません† 。たとえば、次のように(とがあると仮定してgawksed入力を受け取り、期待される出力を吐き出す必要があります。

me@home$ gawk 'match($0, />(.*)</, a){printf("%s|",a[1])} /<\/testable>/{print ""}' test.xml | sed 's/.$//'
Trigger1|2012-06-14T00:03.54|no|no|no
Trigger2|2012-06-15T00:03.54|yes|yes|no

ただし、入力形式が変更された場合、これは惨めに失敗するため、一般的に推奨する解決策ではありません

于 2012-07-26T08:56:42.190 に答える
1

これが純粋なbashソリューションです:

egrep '<trigger>|<message>|<san-.>' test.xml | sed -e 's/<[^>]*>//g' | while read line; do [ $((++i % 5)) -ne 0 ] && echo -n "$line|" || echo $line ; done

ただし、サンプルのようにフォーマットされたファイル(各要素が別々の行にある)でのみ機能し、適切なXML解析/変換を含む他の回答ほど柔軟で信頼性が高くありません。

それはある程度強化することができますが...

于 2012-07-26T13:41:08.450 に答える
1

これは、必要なことを行う XSLT スタイルシートです (test.xsl に保存されます)。

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

<xsl:output method="text"/>
<xsl:strip-space elements="*"/>

 <xsl:template match="testable">
   <xsl:value-of select='trigger'/><xsl:text>|</xsl:text>
   <xsl:value-of select='message'/><xsl:text>|</xsl:text>
   <xsl:value-of select='sales-info/san-a'/><xsl:text>|</xsl:text>
   <xsl:value-of select='sales-info/san-b'/><xsl:text>|</xsl:text>
   <xsl:value-of select='sales-info/san-c'/><xsl:text>&#xA;</xsl:text>
 </xsl:template>

</xsl:stylesheet>

コマンド (ここでは、libxml2 と libxslt がインストールされていることを前提としています。xsltprocは、これらのライブラリを使用するコマンド ライン ツールです):

xsltproc -o sample.txt test.xsl test.xml

sample.txt の内容:

Trigger1|2012-06-14T00:03.54|no|no|no
Trigger2|2012-06-15T00:03.54|yes|yes|no
于 2012-07-26T08:56:50.350 に答える