1

xslt を使用して、適切にフォーマットされた XML 構造をテキスト ファイルから生成する必要があります。私は xslt 変換の初心者で、これは私にとって少し難しいようです。サンプル テキスト ファイルは次のとおりです。最初の部分を省略し、値を引用符で囲んで出力 xml ファイルにマップする必要があります。

Directory:    sample/archive
Name:         20130613-T210002.TXT
---------------------------------------------------------------
"11FCK1GR0026" "G190" "FPB - OK Ship Pt" "A" "11" "XX" "02"
"11FCA1GR0034" "G980" "FPB -San Antonio" "A" "11" "XX" "02"
"11FCA1GR0034" "G160" "FPB -San Antonio" "A" "11" "XX" "02"

以下は、目的の出力 xml 形式です。

<Account>
    <Action>A</Action> <!-- 3rd element in the row-->
    <org>G190</org> <!-- 2nd element-->
    <code>11FCK1GR002611XX</code> <!--concat(1st element, 4th element, 5th element)-->  
    <FiscalYear>2013</FiscalYear> <!--calculate fiscal year from current date -->
    <Info>
        <Action>A</Action> <!-- 3rd element in the row-->
        <org>G190</org> <!-- 2nd element-->
        <code>11FCK1GR002611XX</code><!--concat(1st element, 4th element, 5th element)-->
        <Fieldlab>Acc1</Fieldlab> <!-- Static value-->
        <FieldVal>11FCK1GR0026 </FieldVal> <!-- if field order is 1, map 1st element -->
        <FieldOrd>1</FieldOrd> <!-- Static value-->
    <Info>
    <Info>
        <Action>A</Action>
        <org>G190</org> 
        <code>11FCK1GR002611XX</code>
        <Fieldlab>Acc2</Fieldlab>
        <FieldVal>11</FieldVal>  <!-- if field order is 2, map 5th element -->
        <FieldOrd>2</FieldOrd>
    <Info>
    <Info>
        <Action>A</Action> <!-- 4th element in the row-->
        <org>G190</org> <!-- 2nd element-->
        <code>11FCK1GR002611XX</code>
        <Fieldlab>Acc3</Fieldlab>
        <FieldVal>xx</FieldVal> <!-- if field order is 3, map 6th element -->
        <FieldOrd>3</FieldOrd>
    <Info>
    <Info>
        <Action>A</Action> <!-- 4th element in the row-->
        <org>G190</org> <!-- 2nd element-->
        <code>11FCK1GR002611XX</code>
        <Fieldlab>Acc4</Fieldlab>
        <FieldVal>02</FieldVal> <!-- if field order is 4, map 7th element -->
        <FieldOrd>4</FieldOrd>
    <Info>
    <Info>
        <Action>A</Action> <!-- 4th element in the row-->
        <org>G190</org> <!-- 2nd element-->
        <code>11FCK1GR002611XX</code>
        <Fieldlab>Acc5</Fieldlab>
        <FieldVal>FPB - OK Ship Pt</FieldVal> <!-- if field order is 5, map 3rd element -->
        <FieldOrd>5</FieldOrd>
    <Info>

</Account>
<Account>
    <Action>A</Action> <!-- 3rd element in the row-->
    <org>G980</org> <!-- 2nd element-->
    <code>111FCA1GR003411XX</code> <!--concat(1st element, 4th element, 5th element)--> 
    <FiscalYear>2013</FiscalYear>
    <Info>
        <Action>A</Action> <!-- 3rd element in the row-->
        <org>G190</org> <!-- 2nd element-->
        <code>111FCA1GR003411XX</code><!--concat(1st element, 4th element, 5th element)-->
        <Fieldlab>Acc1</Fieldlab>
        <FieldVal>11FCA1GR0034</FieldVal> <!-- if field order is 1, map 1st element -->
        <FieldOrd>1</FieldOrd> 
    <Info>
    <Info>
        <Action>A</Action>
        <org>G190</org> 
        <code>111FCA1GR003411XX</code>
        <Fieldlab>Acc2</Fieldlab>
        <FieldVal>11</FieldVal>  <!-- if field order is 2, map 5th element -->
        <FieldOrd>2</FieldOrd>
    <Info>
    <Info>
        <Action>A</Action> <!-- 4th element in the row-->
        <org>G190</org> <!-- 2nd element-->
        <code>111FCA1GR003411XX</code>
        <Fieldlab>Acc3</Fieldlab>
        <FieldVal>xx</FieldVal> <!-- if field order is 3, map 6th element -->
        <FieldOrd>3</FieldOrd>
    <Info>
    <Info>
        <Action>A</Action> <!-- 4th element in the row-->
        <org>G190</org> <!-- 2nd element-->
        <code>111FCA1GR003411XX</code>
        <Fieldlab>Acc4</Fieldlab>
        <FieldVal>02</FieldVal> <!-- if field order is 4, map 7th element -->
        <FieldOrd>4</FieldOrd>
    <Info>
    <Info>
        <Action>A</Action> <!-- 4th element in the row-->
        <org>G190</org> <!-- 2nd element-->
        <code>111FCA1GR003411XX</code>
        <Fieldlab>Acc5</Fieldlab>
        <FieldVal>FPB -San Antonio</FieldVal> <!-- if field order is 5, map 3rd element -->
        <FieldOrd>5</FieldOrd>
    <Info>
</Account>

このファイルを生成するのを手伝ってくれる人はいますか。前もって感謝します!

4

2 に答える 2

2

この変換は 2 つのフェーズで行います (分割することでタスクを簡素化します)。最初のフェーズでは、元のテキストと同型の XML を生成します。2 番目のフェーズでは、XML を再構築します。

フェーズ 1 は次のようなものです。

<xsl:template name="main">
<doc>
  <xsl:for-each select="tokenize(unparsed-text('input.txt'), '\r?\n')
                           [starts-with(., '&quot;')]">
    <row>
      <xsl:analyze-string select="." regex='\"[^"]*?\"'>
        <xsl:matching-substring>
          <col><xsl:value-of select="."/></col>
        </xsl:matching-substring>
      </xsl:analyze-string>
    </row>
  </xsl:for-each>
</doc>
</xsl:template>

フェーズ 2 は次のようなものです。

<xsl:template match="doc">
  <Accounts>
    <xsl:apply-templates/>
  </Accounts>
</xsl:template>

<xsl:template match="row">
  <xsl:variable name="row" select="."/>
  <Account>
    <Action><xsl:value-of select="col[4]"/></Action>
    <org><xsl:value-of select="col[2]"/></org>
    <xsl:variable name="code" select="concat(col[1], col[4], col[5])"/>
    <code><xsl:value-of select="$code"/></code>
    <FiscalYear><xsl:value-of select="year-from-date(current-date())"/></FiscalYear>
    <xsl:for-each select="1 to 5">
      <xsl:variable name="p" select="."/>
      <Info>
        <Action><xsl:value-of select="$row/col[4]"/></Action>
        <org><xsl:value-of select="$row/col[2]"/></org>
        <code><xsl:value-of select="$code"/></code>
        <FieldLab>Acc<xsl:value-of select="."/></FieldLab>
        <FieldVal><xsl:value-of select="$row/col[(1,5,6,7,3)[$p]]"/></FieldVal>
        <FieldOrd><xsl:value-of select="."/></FieldOrd>
     </Info>
   </xsl:for-each>
  </Account>
</xsl:template> 

2 つのフェーズをつなぎ合わせるには、さまざまな方法があります。単一のスタイルシート内で実行できます (最初のフェーズの結果を変数に入れてから、2 番目のフェーズで処理します)。または、シェル スクリプト、Ant、XProc、または xmlsh から順番に実行できます。またはカスタム Java アプリケーション。

于 2013-06-24T23:02:56.760 に答える
0

W3C が述べているように:

XSL Transformations (XSLT 2.0) は、XML ドキュメントを他の XML ドキュメント、テキスト ドキュメント、または HTML ドキュメントに変換するための言語です。

XSLT はテキスト ファイルを解析するように設計されていないため、この方法で XSLT を使用すると冗長になり、読みにくくなります。@JimGarrison が指摘したように、Python ソリューションを含めましたが、より適切な文字列 I/O 言語は他にもたくさんあります。XSLT を使用しなければならないビジネス上の強いニーズがない限り、以下のコードを見て、選択した言語に翻訳することを強くお勧めします。

あなたは古典的なXY Problemを尋ねたと思うので、ここで見ることができる Python の代替バージョンをコーディングしました: http://codepad.org/JWNbqrwD。これにはファイル I/O は含まれていませんが、追加するのが非常にトリッキーな変更ではありません。

いくつかの点として、出力は XML ではありません。単一のルート要素がなく、youtInfoタグが正しく閉じられないため、このスクリプトも同様です。

import re
from datetime import datetime

data = """Directory:    sample/archive
Name:         20130613-T210002.TXT
---------------------------------------------------------------
"11FCK1GR0026" "G190" "FPB - OK Ship Pt" "A" "11" "XX" "02"
"11FCA1GR0034" "G980" "FPB -San Antonio" "A" "11" "XX" "02"
"11FCA1GR0034" "G160" "FPB -San Antonio" "A" "11" "XX" "02"
"""

output = ""

# Split on new lines start at line 3.
for line in data.split("\n")[3:]:
    fields = re.findall('"([^"]*)"',line) #Find all 
    newAccount = ""
    if len(fields) == 7:
        action, org, code = fields[3],fields[2], "".join([fields[0],fields[3],fields[4]])
        newAccount = "<Account>\n" + \
            "\t<Action>%s</Action>\n" % action + \
            "\t<org>%s</org>\n" % org + \
            "\t<code>%s</code>\n" % code + \
            "\t<FiscalYear>%s</FiscalYear>\n" % datetime.now().year
        orderMap = [(1,0),(2,4),(3,5),(4,6),(5,2)]
        for pos,fieldNum in orderMap:
            newAccount += "\t<Info>\n" + \
                "\t\t<Action>%s</Action>\n" % action + \
                "\t\t<org>%s</org>\n" % org + \
                "\t\t<code>%s</code>\n" % code + \
                "\t\t<Fieldlab>Acc%s</Fieldlab>\n" % pos + \
                "\t\t<FieldVal>%s</FieldVal>\n" % fields[fieldNum]+ \
                "\t\t<FieldOrd>%s</FieldOrd>\n" % pos + \
            "\t<Info>\n"
        newAccount += "</Account>\n"

    output += newAccount

print output
于 2013-06-24T23:57:13.433 に答える