2021年7月29日木曜日

Bloggerでコードを見やすく表示するために

今回は全然くそみたいな記事だけど、

コードをきれいに見せたくて、

スタイルシートいじったり、いろいろやったことあるんだけど、

一番簡単なのはVSCでコピペすればいい

func createStruct(xmlstr string, tag *Tag) {
    log.Println("info: createStruct Start")

    var tmpTag Tag
    var attrExist bool
    var tmpAttr Tag
    var sTextCount int
    currentTag := tag // 現在のタグ位置は状況によって移動する

こんな感じで一部だけコピペしてるだけなんだけど、

綺麗に張り付けられる。

もうこれでいいよね?




RaspberryPi4の熱暴走対策

RaspberryPi4がクーラーのない部屋で1.5M稼働してると、熱暴走することがあった。

しかたないので、スマホ用クーラー付けてみた。

今のところ、1.5M動作でも55度から57.4度あたりをうろついている。

あ、写真は間違って裏側につけてた時の写真、

PINの配置がある表側につけないとだめよ?




RaspberryPi4の温度と周波数を手軽に表示したかった(そんだけ)

RaspberryPi4の温度と周波数を手軽に見たいなと思ってalias 作った(そんだけ)

以下を.bashrcの適当なところに設定してやれば、tempとかfreqで出てくる。

alias temp='echo "scale=3;"$(cat /sys/class/thermal/thermal_zone0/temp) / 1000 | bc'
alias freq='cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq'

2021年7月27日火曜日

Golang gob

 gobってのがあるんだってさ

https://play.golang.org/p/zrediqzUguW

使いどころとしてはバッファを介して、エンコード、デコードするだけの代物らしい

これ、、、要る?

JSONやXMLの代わりになるって言ってるんだけど、

XML DBのような用途にはならないし、Mongo DB的な発展もできないし、

値を順番に何かにDecodeするだけだろ?

・・・手でやれや?

2021年7月26日月曜日

キッチン用の小さいゴミ箱(三角コーナーの代わり)

 キッチンの三角コーナーがダサくて、ダイソーの紙袋をつかっていた。

だけど、15枚で100円なので、結構毎日取り換えちゃうし、これもちょっとなぁと思い始めていた。
そこで、元の木阿弥だけど、このサイズを元にしてゴミ箱を作ることにした。
デザインはいつもの通り、onShapeを使っている。
onShapeは最高に軽くて、インストール不要でブラウザで動くのでとても重宝している。
また、AndroidやiPhone、iPadアプリもあるんで、スマホでも軽快に動作し、電車通勤の最中でもデザインできるようになるのがうれしい。


とりあえずできたので、こんな感じにシンクの脇に設置した。
しばらく使ってみる。

2021年7月15日木曜日

Golangで自前XML2JSON出来ましたわ

動画の説明
Sedna XML Databaseにbase64エンコードされた画像も含んだタグが記録されていて、XQuery使ってTitleでソートし、先頭の5件を取得、その後、Golangで作ったXML2JSONで変換し、クライアントへ送り返している。
クライアントで取得したJSONをコピペして、巷のサイトのJSON Validator使ってフォーマットしている。

巷のサイトさんのチェックが遅すぎて笑ったw

XQueryのReturn値全体を<DATA>タグで括り、DATAタグのプロパティで、OUTPATHを指定することで、XMLタグの任意の位置をルートに指定できるようにした。さらに、FORCEARRAYプロパティで、強制配列化も複数個所指定できるようにした。
おそらく世界中のどのXML2JSONよりまともに動くが今のところ公開する気はない。

見て欲しいところは、最後のチャーハンの項目ね
XMLだとチャーハンはTAGS/nameに1項目しかないんだけど、
FORCEARRAYでパス指定してあると、1項目でも[]で囲われて強制的に配列扱いになっている。

こういうのはXMLを一度構造体などを使ってメモリ上に展開し、JSONを組み立てる時にパスを確認し、強制配列表現にするかどうかってことをやらないといけない。

まぁここまで書けば誰でもできることだろう?



 

2021年7月14日水曜日

golangでの文字列連結問題(有名な大問題らしい)

これだと、ループ回数多いときに10分かかっても終わらなかった
for i:=0;i<1000;i++{
str += "&#13"
}
return str

これだと、0.1秒かからねぇ
buf := make([]byte, 0)
for i:=0;i<1000;i++{
buf = append(buf, "&#13;"...)
}
return string(buf)
最初のは、strがいちいちメモリ確保、コピー、解放され、あまつさえガベージコレクションも動くようだ。
下のは、実はあれこれ試してみて一番早かった。
byte配列作って、Appendしていくのは早いみたいなんだよなぁ
よくわかんねぇよ
いいね!
コメントする
シェア

2021年7月10日土曜日

encoding/xml使ってXMLをJSON変換

 やりたくなかったけど、大体できた。

以下テストコード

package xml2json

import "testing"

func TestXml2JSON(t *testing.T) {
    //  xmlstr := "<data>aiueo</data>"
    //  xmlstr := "<data>aiueo</data><data>bbbbb</data>"

    xmlstr := "<DATA TYPE=\"JSON\" FORCEARRAY=\"//LIST/ITEM //LIST/ITEM/TAGS\">" +
        "<LIST>" +
        "  <ITEM id='1'>" +
        "    <UUID>0f164f93-fe33-44d4-8f2a-f94518b7cb51</UUID>" +
        "    <TITLE>たいとるなんな</TITLE>" +
        "    <TAGS>(:コメントはどうなるの?:)" +
        "      <name ID='1' IMPORTANCE='20'>あいうえお</name>" +
        "      <name>かきくけこ</name>" +
        "      <OTHER>aaaa</OTHER>" +
        "      <name>さしすせそ</name>" +
        "    </TAGS>" +
        "  </ITEM>" +
        "  <ITEM>" +
        "    <UUID>f36ea96f-97a8-438e-8656-ca7365f23df9</UUID>" +
        "    <TITLE>たいとるなんです</TITLE>" +
        "    <TAGS>(:コメントはどうなるの?:)" +
        "      <name>あああ</name>" +
        "      <name>いいいい</name>" +
        "      <name>ううううう</name>" +
        "    </TAGS>" +
        "  </ITEM>" +
        "</LIST>" +
        "</DATA>"

    xml2json(xmlstr)
}


変換後(改行はないけどフォーマットした)

{
    "DATA": {
        "-TYPE""JSON",
        "-FORCEARRAY""//LIST/ITEM //LIST/ITEM/TAGS",
        "LIST": {
            "ITEM": [
                {
                    "-id""1",
                    "UUID""0f164f93-fe33-44d4-8f2a-f94518b7cb51",
                    "TITLE""たいとるなんな",
                    "TAGS": {
                        "name": [
                            {
                                "-ID""1",
                                "-IMPORTANCE""20",
                                "#text""あいうえお"
                            },
                            "かきくけこ",
                            "さしすせそ"
                        ],
                        "OTHER""aaaa"
                    }
                },
                {
                    "UUID""f36ea96f-97a8-438e-8656-ca7365f23df9",
                    "TITLE""たいとるなんです",
                    "TAGS": {
                        "name": [
                            "あああ",
                            "いいいい",
                            "ううううう"
                        ]
                    }
                }
            ]
        }
    }
}

あと考慮するのは以下2点

1.どこのパスからパースするかの指定をアトリビュートに持つ

2.FORCEARRAYの機能実装

どちらも目処は立っている

2021年7月7日水曜日

XML2MAPもダメだったわ

 なんでこんなバグがあるんだろうなぁ

package xml2json

import (
    "fmt"
    "log"
    "strings"

    "github.com/sbabiv/xml2map"
)

func xml2json(xmlstr string) {
    decoder := xml2map.NewDecoder(strings.NewReader(xmlstr))
    resulterr := decoder.Decode()

    if err != nil {
        log.Printf("info: err = %v\n", err)
    } else {
        log.Printf("info: result = %v\n", result)
        /*
            2021/07/07 22:48:58 info: result = map[DATA:map[@FORCEARRAY://LIST/ITEM //LIST/ITEM/TAGS @TYPE:JSON LIST:map[ITEM:[map[@id:1 TAGS:map[OTHER:aaaa name:[map[#text:あいうえお @ID:1 @IMPORTANCE:20] map[name:かきくけこ] map[name:さしすせそ]]] TITLE:たいとるなんな UUID:0f164f93-fe33-44d4-8f2a-f94518b7cb51] map[TAGS:map[name:[あああ いいいい ううううう]] TITLE:たいとるなんです UUID:f36ea96f-97a8-438e-8656-ca7365f23df9]]]]]
            あれ、map[name:かきくけこ] map[name:さしすせそ] ここがnameでまとまってないバグじゃん・・・
            ありえねー---
            なんでこんなバグがあるんだー
            これやはり、XMLからgoの仮想ファイルシステム作って考えた方がいいかもしれない・・・
        */
    }

    v := result["DATA"]
    log.Printf("info: result[\"DATA\"] = %v\n", v)
    // DATAのアトリビュートは以下の様に取得できる
    ForceArray := strings.Split(result["DATA"].(map[string]interface{})["@FORCEARRAY"].(string), " ")
    Type := strings.Split(result["DATA"].(map[string]interface{})["@TYPE"].(string), " ")
    log.Println("info: ForceArray[0] = ", ForceArray[0], " ForceArray[1] = ", ForceArray[1], " Type = ", Type)
    // DATAの子ノードはLISTという決まりはないので以下のような取り方はダメ
    //やるとしたらDATAも含めて回さないといけない
    l := result["DATA"].(map[string]interface{})["LIST"]

    fmt.Printf("DATA/LIST: %v\n", l)
}

んで、テスト

package xml2json

import "testing"

func TestXml2JSON(t *testing.T) {
    xmlstr := "<DATA TYPE=\"JSON\" FORCEARRAY=\"//LIST/ITEM //LIST/ITEM/TAGS\">" +
        "<LIST>" +
        "  <ITEM id='1'>" +
        "    <UUID>0f164f93-fe33-44d4-8f2a-f94518b7cb51</UUID>" +
        "    <TITLE>たいとるなんな</TITLE>" +
        "    <TAGS>(:コメントはどうなるの?:)" +
        "      <name ID='1' IMPORTANCE='20'>あいうえお</name>" +
        "      <name>かきくけこ</name>" +
        "      <OTHER>aaaa</OTHER>" +
        "      <name>さしすせそ</name>" +
        "    </TAGS>" +
        "  </ITEM>" +
        "  <ITEM>" +
        "    <UUID>f36ea96f-97a8-438e-8656-ca7365f23df9</UUID>" +
        "    <TITLE>たいとるなんです</TITLE>" +
        "    <TAGS>(:コメントはどうなるの?:)" +
        "      <name>あああ</name>" +
        "      <name>いいいい</name>" +
        "      <name>ううううう</name>" +
        "    </TAGS>" +
        "  </ITEM>" +
        "</LIST>" +
        "</DATA>"

    xml2json(xmlstr)
}


で、ソース中にも書いたけどさ

        /*
            2021/07/07 22:48:58 info: result = map[DATA:map[@FORCEARRAY://LIST/ITEM //LIST/ITEM/TAGS @TYPE:JSON LIST:map[ITEM:[map[@id:1 TAGS:map[OTHER:aaaa name:[map[#text:あいうえお @ID:1 @IMPORTANCE:20] map[name:かきくけこ] map[name:さしすせそ]]] TITLE:たいとるなんな UUID:0f164f93-fe33-44d4-8f2a-f94518b7cb51] map[TAGS:map[name:[あああ いいいい ううううう]] TITLE:たいとるなんです UUID:f36ea96f-97a8-438e-8656-ca7365f23df9]]]]]
            あれ、map[name:かきくけこ] map[name:さしすせそ] ここがnameでまとまってないバグじゃん・・・
            ありえねー---
            なんでこんなバグがあるんだー
            これやはり、XMLからgoの仮想ファイルシステム作って考えた方がいいかもしれない・・・
        */


ここよ、どうなってんだよ?

マップがnameでまとまってねーんだよ

おそらく途中に<OTHER>挟んだからだよな?

なんでnameでまとまらないの?

もうあれだ、、、疲れたわ、、、


golangによるXMLのパース

これでいけるかもしれない

やってみたらちゃんとまとまってくれてる、これなら回せるかもしれない

あーgo-xmldomもダメだわ

 何がダメって、

<list>

 <name>あいうえお</name>

 <name>かきくけこ</name>

 <other>OTHER</other>

 <name>さしすせそ</name>

</list>

で、list.childrenを取得すると、nameとotherだけ取得できるようになっておらず、

children[0],children[1]がnameのあいうえお、かきくけこを指していて、children[2]がOTHER、children[3]がnameのさしすせそを指すようになっている。

なんでもう一段まとめてくれねぇんだよ・・・

XMLてのはフォルダ構造に似ていて、

上記まとめ方だと、nameというフォルダが複数あるかのような動きになってしまっている。

XMLデータの扱いとしては、フォルダに例えて説明すると、

nameフォルダの下にファイルが複数あって、そのファイルの中にテキストやアトリビュートが入っているかのような造りにしてくれないと全然使い勝手違うんだよ

まぢわかってねぇわ・・・

XMLはDOMで扱ったほうがいいわ

XMLからJSONへの変換をしようとしていて、encoding/xml使ったり、XSLで変換かけようかと思ったけど、XSLTは難解で、考え方は分ってきたけど、組みづらい・・・

やはりXMLはDOMで扱わないとダメよ

encoding/xmlとか使っても結局DOM作ろうとしちゃうし、DOM作らないと、XMLの表記方法への対応は出来ない。

たとえば、以下のようにnameが連続していないとき、name項目が一つしかないとき、nameの下に子ノードがあるときなど、汎用的なXMLでは、SAXやxsl的な方法での変換なんて出来ない。

<root>

 <list>

  <name>aiueo

    <special>あいうえお</special>

  </name>

  <name>kakikukeko</name>

  <URL>http://www.blablabla.com</URL>

  <name>sasisuseso</name>

 </list>

</root>

SAXやXSLは、きまった形のXMLでない対応できない。

この考え方が、xslを使えない奴にしてしまっている。

ていうか、xslで出来ることがHTML変換くらいなものなのだが、

JavaScript系のエンジニアは、JSONでそのまま扱いたいからxslなんて勉強しない。

そして余計にXMLが嫌われていく

xslもオブジェクト指向に毒されてしまっているのだと思う。


golangやってると、オブジェクト指向なんてどうでもよくなる。

(まったくオブジェクト指向なんて悪い夢を見ていたようだよ)

話を戻して、JSONへの変換元となるXMLは、形が無限の種類のXMLなので、SAXやXSLでは絶対に無理だ。

例えば上記の場合、name以下は全部強制的に配列にしたい。

nameの途中にURLタグが出てきちゃうので、nameで要素をまとめてJSON配列にしないといけない。

これは、encoding/xmlのtokenじゃ無理

一度読み込んでまとめ、ソートするなど工夫が必要だ。

つまりそれってDOMだよ


強制配列を実現するために全体をDATAタグで括って、プロパティでForceArrayを指定して変換できるように考えていた。

まず、このアトリビュートの取得をして、複数のXPATHをXSLのVariableに配列としてSplitしようかと思ったのだけど、xsl2.0じゃないとtokenize使えないし、xsl2.0なんて誰も実装してないし、SAXXONくらいだし、俺Java嫌いだし絶対に使わねー

go-xmldomでxml2json作ろうかと思ってまずはxmldomのテストプログラムを動かしてみた。

名前はxml2json.goだけど、機能はxml2jsonじゃありません。

単にテストプログラムをそのまま動かしただけです

Qiitaみたいですみません

===xml2json.go===

package xml2json

import (
    "fmt"

    xmldom "github.com/subchen/go-xmldom"
)

func xml2json() {
    xml := `<testsuite tests="2" failures="0" time="0.009" name="github.com/subchen/go-xmldom">
    <testcase classname="go-xmldom" name="ExampleParseXML" time="0.004"></testcase>
    <testcase classname="go-xmldom" name="ExampleParse" time="0.005"></testcase>
</testsuite>`

    doc := xmldom.Must(xmldom.ParseXML(xml))
    root := doc.Root

    name := root.GetAttributeValue("name")
    time := root.GetAttributeValue("time")
    fmt.Printf("testsuite: name=%v, time=%v\n", name, time)

    for _node := range root.GetChildren("testcase") {
        name := node.GetAttributeValue("name")
        time := node.GetAttributeValue("time")
        fmt.Printf("testcase: name=%v, time=%v\n", name, time)
    }
}


んで、テストになってないテストプログラム

package xml2json

import "testing"

func TestXml2JSON(t *testing.T) {
    xml2json()
}



go test -vで動かすと以下の様に出てくる

=== RUN   TestXml2JSON

testsuite: name=github.com/subchen/go-xmldom, time=0.009

testcase: name=ExampleParseXML, time=0.004

testcase: name=ExampleParse, time=0.005

--- PASS: TestXml2JSON (0.00s)

PASS

ok      xml2json        0.004s





2021年7月5日月曜日

XMLからJSONへ

簡単に考えていたのだが、XML表記をそのままJSONへ変換することは出来ない。

簡単に言うと2つ問題がある。

1.XMLから配列への扱い

入力XML(NAMEが1つのとき)

<LIST>
 <NAME>あいうえお</NAME>
 <NAME>かきくけこ</NAME>
 </LIST>

出力JSON(NAMEが1つのとき)

{
    "LIST": {
        "NAME""あいうえお"
    }
}

入力XML(NAMEが1つ以上とのき)

<LIST>
 <NAME>あいうえお</NAME>
 <NAME>かきくけこ</NAME>
 </LIST>

出力JSON(NAMEが1つ以上のとき)

{
    "LIST": {
        "NAME": [
            "あいうえお",
            "かきくけこ"
        ]
    }
}

これは非常にわかりやすい

XMLのNAMEが1件なら配列にはならないのだが、

1件以上あれば鍵カッコで囲われて配列になっている。

なので、XMLの特定のタグについては、

強制配列化を行いたいという要望があちこちのXML2JSONで散見されている。

2.アトリビュート有り無し混在

続いて、アトリビュートの扱いだ。

入力(アトリビュート有り無し混在XML)

<LIST>
 <NAME ID='1' IMPORTANCE='20'>あいうえお</NAME>
 <NAME>かきくけこ</NAME>
</LIST>

出力JSON(アトリビュート有り無し部のアクセスの仕方が違ってしまう

{
    "LIST": {
        "NAME": [
            {
                "-ID""1",
                "-IMPORTANCE""20",
                "#text""あいうえお"
            },
            "かきくけこ"
        ]
    }
}

これ、非常にまずい、あいうえおは#textになってて、かきくけこは普通に配列に入っている。ついでにXMLのアトリビュート名にはハイフンがプレフィックスとしてついている。

しかし、XMLからJSONへの変換の仕方としてはこれが一般的なのだ。


上記1の問題から、タグごとにアトリビュートでFORCEARRAYの設定を付けたら配列になるような仕様にするべきと考える。


上記問題2の結果から同じ階層で同じタグ名で、アトリビュート有り無し混在したXMLはJSONへの変換に用いてはならないことになる。


んで、これら2つの問題を考慮したうえで、

XMLからJSONへの変換をもう一度考えてみたが、

やり方として別にgolangでやる必要なんかなかったのでは?

そもそもXMLなんだから、なんでXSLTしないの?

という事に気が付いた。

んで、今色々と試行錯誤中

2021年7月1日木曜日

goxml2jsonのバグが修正されないので、自前で作ろうとまずはXMLを列挙する部分を作った

goxml2jsonの強制配列化はバグがある

詳細はこちら

最初の1行にしか強制配列化が適用されない。

書き込みの最後にアトリビュートでどうたら書かれているけど、

これはただの提案であり、XML的には単なるアトリビュートなので、全く意味のない書き込みだ。

しかも、指定した場所以降、すべて配列化されてしまう。

そして、配列化する場所は一か所しか指定できない。


仕方ないので、自前で作ろうと思う。

とはいえ、encoding/xmlは使う。

こちらにPlayGroundの例を置いておく

まずは任意のXMLを列挙する部分を作った。

encoding/xmlを使うときに、なぜか皆さん、構造体を作って割り当てるやり方しかしていない。

JSONなんざ文字列なので、XMLを列挙しながら対応していけばいいんだよ

まずは列挙だけしたからあとは勝手に作ればいい