[Go] [JS]また、marc形式の処理について

あいさつ、私はすでにMARC形式に関する2つの記事(ギーク時、数千)を書きました。



今日、技術的な詳細が記載された記事があります。ソリューションのコードをクリーンアップし、そこから魔法を取り除き、一般にそれをとかしました。



カットの下:goとjsの友情、marc形式への憎しみ







それで、「カーネル」から始めましょう-marc形式で作業するためのパッケージはgoで書かれており、テスト範囲は63%です。

https://github.com/t0pep0/marc21



パッケージ全体の「ヘッド」-MarcRecord構造



type MarcRecord struct { Leader *Leader directory []*directory VariableFields []*VariableField }
      
      







そして、それで動作する2つのメソッドのみ、これらは



 func ReadRecord(r io.Reader) (record *MarcRecord, err error) func (mr *MarcRecord) Write(w io.Writer) (err error)
      
      







率直に言って、私は彼らに立ち止まる意味がありません。 唯一のことは、ReadRecordがReaderの最後に到達すると、err == io.EOFを返すことです。



さらに見ると、LeaderおよびVariableField構造、およびVariableFieldがハッシュマップではなくスライスとして作成される理由に興味があります(すべての標準および常識とは対照的に、2つの異なるフィールド(コンテンツ内)の存在の状況が1つのタグで可能であり、先に実行されますサブフィールドの場合、これも真実だと言います)



 type Leader struct { length int Status byte Type byte BibLevel byte ControlType byte CharacterEncoding byte IndicatorCount byte SubfieldCodeCount byte baseAddress int EncodingLevel byte CatalogingForm byte MultipartLevel byte LengthOFFieldPort byte StartCharPos byte LengthImplemenDefine byte Undefine byte }
      
      







リーダーの構造、適切な単語、興味深いものは何もない、フラグのセット、エクスポートされないものは、シリアライゼーション/デシリアライゼーションにのみ使用されます。 2つのメソッドがアタッチされています-シリアライゼーションとデシリアライゼーションは、{Read、Write} Recordから呼び出されます(他の構造の場合も同様です。



 type VariableField struct { Tag string HasIndicators bool Indicators []byte RawData []byte Subfields []*SubField }
      
      







「可変フィールド」の構造。 すぐにいくつかの興味深い点に注目したい-3文字のタグ、RawData-は文字列にすることができますが、私にとってはバイトの配列を扱う方が便利でした。 シリアル化中に、フィールドにサブフィールドがない場合(len(Subfields)== 0)、RawDataが書き込まれます。そうでない場合、RawDataは無視されます



 type SubField struct { Name string Data []byte }
      
      







名前-1文字、切り捨て

データ-繰り返しますが、文字列を使用できますが、私はそう決めました...



パッケージには特別なニュアンスはありません。一度に言えることは1つだけです-フィールドを追加する前に、フィールドに少なくともタグ以外のものがあることを確認してください。そうしないと、高いものについて考えて、OPAC \ IRBISへのエクスポートが機能しない理由を理解しようとすることに多くの時間を費やす危険があります



データを変更しないが、実際には、あるレコードファイルを別のレコードファイルに単純にコピーするサンプルコード

 package main import ( "github.com/t0pep0/marc21" "io" "os" ) func main() { orig := os.Args[1] result := os.Args[2] origFile, _ := os.Open(orig) resultFile, _ := os.Create(result) for { rec, err := marc21.ReadRecord(origFile) if err != nil { if err == io.EOF { break } panic(err) } //  -   .... err = rec.Write(resultFile) if err != nil { panic(err) } } }
      
      







では、 https://github.com/HerzenLibRu/BatchMarcに進みましょう



実際、これは、上記で説明したライブラリが接続されたjsインタープリターhttps://github.com/robertkrimen/otto/です。



 func main() { marcFile, err := os.Open(os.Args[1]) outFile, _ := os.Create(os.Args[2]) jsFile, _ := os.Open(os.Args[3]) jsBytes, _ := ioutil.ReadAll(jsFile) jsRules := string(jsBytes) if err != nil { return } for { rec, err := marc21.ReadRecord(marcFile) if err != nil { if err == io.EOF { break } panic(err) } if rec == nil { break } res := new(marc21.MarcRecord) js := NewJSMachine(rec, res) err = js.Run(jsRules) if err != nil { panic(err) } res.Write(outFile) } }
      
      







上記のコードとの違いは、ここではjsでファイルを開き、ルールを渡してjsマシンを作成することです。



jsマシンとそのコンストラクターを詳しく見てみましょう。



 type jsMachine struct { otto *otto.Otto source *marc21.MarcRecord destination *marc21.MarcRecord } func NewJSMachine(source, destination *marc21.MarcRecord) (js *jsMachine) { js = new(jsMachine) js.otto = otto.New() js.otto.Run(classJS) js.otto.Set("LoadSource", js.fillSource) js.otto.Set("WriteResult", js.getResult) js.source = source js.destination = destination return js } func (js *jsMachine) Run(src string) (err error) { _, err = js.otto.Run(src) if err != nil { return err } return nil }
      
      







ご覧のとおり、すべてがシンプルで装飾的であり、埋め込みは意識的に使用されていません。



2つの関数が標準のオットー配布に追加されます-LoadSourceおよびWriteResult、さらにクラスコンストラクター(MarcRecord、Leader、VariableField、VariableSubField)が追加されます



関数の実装については詳しく説明しませんが、すべてのjs変数を削減できるObject型があるという点で興味深い点に注意を払います。 ObjectタイプにはCallメソッドがあり(Set / Getメソッドも同様)、変数メソッドを呼び出すことができます。 Duck here-Object.Callは、ネストされたクラスのメソッドの呼び出しを許可しません。

  source := call.Argument(0) if !source.IsObject() { return otto.FalseValue() } object := source.Object() //   jsValue, _ := object.Get("VariableField") jsVariableFields := jsValue.Object() jsValue, _ = jsVariableFields.Call("length") //   -   jsValue, _ = object.Call("VariableField.length")
      
      





それはタイプの誤りで誓うことは注目に値します、そして、このため、正しい決定は長い間心を越えました。



JSについて一言。 人為的に作成された変数はありません。MarcRecordコンストラクターからクラスのインスタンスを作成し、LoadSource(インスタンス)でロードして、スクリプトの最後に変更を送信し、WriteResult(インスタンス)を指定します。



PullRequest \ IssueRequest-ようこそ。



All Articles