2013年7月18日木曜日

【XSLT】 XSLTで2つのXMLをマージしてみた

XSLTで2つのデータのマージをしたいとおもって色々探しまわったけど、見つからなかったので自作してみた。

こういう用途ってないのかな??

saxonでしか確認してない。そもそも2.0でしか動かない!

call-templateはネストすると処理が重くなるため、apply-templatesで処理してます。
nodes1に放り込んだxmlに対して、nodes2を上書きしていきます。

要素の順番はnodes1側に引きづられ、nodes2側にしかない要素(追加したい要素)は兄弟要素として末尾に追加されます。

マージしたxmlに対してxpathで取得する際には問題が起きにくいですが、ノード番号等で取得するような場合は注意が必要です。

さて、次はドキュメント比較用のXSLTを作らねば・・・

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="@*|node()" mode="marge">
 <xsl:param name="nodes1" as="item()*" />
 <xsl:param name="nodes2" as="item()*" />
 <xsl:variable name="node1" select="$nodes1[1]" as="item()*" />
 <xsl:variable name="node2" as="item()*">
  <xsl:choose>
   <xsl:when test="$node1">
    <xsl:copy-of select="$nodes2[name() = $node1/name()][position() = 1]" />
   </xsl:when>
   <xsl:otherwise>
    <xsl:copy-of select="$nodes2[1]" />
   </xsl:otherwise>
  </xsl:choose>
 </xsl:variable>
 <xsl:variable name="nodes1After" as="item()*">
  <xsl:copy-of select="$nodes1[position() != 1]" />
 </xsl:variable>
 <xsl:variable name="nodes2After" as="item()*">
  <xsl:choose>
   <xsl:when test="$node1">
    <xsl:copy-of select="$nodes2[not(name() = $node1/name() and position() = 1)]" />
   </xsl:when>
   <xsl:otherwise>
    <xsl:copy-of select="$nodes2[position() != 1]"></xsl:copy-of>
   </xsl:otherwise>
  </xsl:choose>
 </xsl:variable>
 
 <xsl:choose>
  <xsl:when test="not($node1)">
   <xsl:copy-of select="$node2" />
  </xsl:when>
  <xsl:when test="$node1">
   <xsl:element name="{$node1/name()}">
    <xsl:apply-templates select="$node1/@*" />
    <xsl:apply-templates select="$node2/@*" />
    <!-- 子要素 -->
    <xsl:apply-templates select="self::node()" mode="marge">
     <xsl:with-param name="nodes1" select="$node1/node()" />
     <xsl:with-param name="nodes2" select="$node2/node()" />
    </xsl:apply-templates>
   </xsl:element>
   <xsl:apply-templates select="self::node()" mode="marge">
    <xsl:with-param name="nodes1" select="$nodes1After" />
    <xsl:with-param name="nodes2" select="$nodes2After" />
   </xsl:apply-templates>
  </xsl:when>
  <xsl:otherwise />
 </xsl:choose>
</xsl:template>
</xsl:stylesheet>

2013年6月26日水曜日

【Javascript】クラス化ってどうよ?

すげー久々に更新したりしてみたり。

最近、JavaScriptと仲良しです。
といっても、ブラウザ向けじゃなくて、Adobe向けっていうのがまた変なんですが・・・

InDesign、Illustrator、Photoshop、Acrobat(いじった時間が多い順)とかやってて思ったのが、
クラス化してない人が多いな、と。

JavaScriptはなんちゃって(プロトタイプ)オブジェクト指向なので、クラス化する意味あるのかなーとかずっと思ってたんだけど、やってみると超便利だったっていうことがわかった。

結局、Adobe系のjsについてはデータドリブンな部分がhtmlに比べて少なく、メソッドチェーンが効果を発揮するのは自分でデータセットを準備した後のようなイメージ。

じゃあ、データ揃うまではどうすんの?って話に成るんだけど、関数やらでごまかしても限界があって二度手間、三度手間が発生しちゃう。

かといって、クラス化してるJavaScriptはあまり無かったもんだからさぁ困ったっていう話。

今、サンプルが手元にないので偉そうなこと言えないな・・・

今度アップします。


2013年4月12日金曜日

【Linux】RAID1が縮退運転しおった


やられたぜ・・・・

/dev/md0:
        Version : 1.2
  Creation Time : Mon Dec  3 17:39:14 2012
     Raid Level : raid1
     Array Size : 97590144 (93.07 GiB 99.93 GB)
  Used Dev Size : 97590144 (93.07 GiB 99.93 GB)
   Raid Devices : 2
  Total Devices : 1
    Persistence : Superblock is persistent

    Update Time : Fri Apr 12 00:31:47 2013
          State : clean, degraded
 Active Devices : 1
Working Devices : 1
 Failed Devices : 0
  Spare Devices : 0

           UUID : 84c532e6:58e0cc48:c30029c5:37eb4163
         Events : 731

    Number   Major   Minor   RaidDevice State
       0       0        0        0      removed
       1       8       18        1      active sync   /dev/sdb2

交換用のHDD買うか・・・・

とりあえず買ってみたものの、sdbのgrubが起動しない。

環境はこんなかんじ
Ubuntu 12.04
md0: sda2 sdb2
md1: sda3 sdb3
md2: sda4 sdb4

grubのOS選択画面で再起動がかかり、BIOS画面と行ったり来たりする。
grubの設定を変更してもだめ、grubシェルでlsしようとしたり、insmodしようとして、補完でTABキー打つと再起動する。
意味分かんない。

旧sdaから新sdaを全部コピーしてみたらできたので、物理的に新しいHDDにした状態で上の状態になった。

あとはmdadm /dev/md0 -a /dev/sda2とかしてリビルドして完了。

なぜか1パーテーションがビジーって言われたけど、再起動したら無問題だった。
よかったよかった。

2013年4月4日木曜日

【CakePHP】$this->renderとbeforeRenderの関係

今日はまった出来事。

権限によってviewを変更しようと思って、どこで調整しようかなーと考えてて、
beforeRenderならひと通りできそうだしいいじゃね?!と思ってやってみたらダメだった。

やろうとしている人が居られたら注意を。

■環境
・CentOS 6.5
・PHP 5.3
・CakePHP 2.3.1

なんでかなーと思って調べました。
Controllerの順序は↓な感じだと思う。

beforeFilter
(action)
beforeRender
(view)
afterFilter

使ってる人はご存知の通り、Controller中で$this->renderを使用したタイミングでviewへ処理が移行してしまい、Controllerでの処理が続行できない。
これは、autoRenderが働くためと思われる。詳細は調べてないのです。
$this->outputを呼び出しているせいで、その時点でview用のデータがセットされてしまうとのこと。

んで、重要なのはbeforeRenderと$this->renderのタイミング。

どうやら、beforeRenderはこの$this->outputを呼び出したあとに処理される模様。
普通に考えてみりゃそりゃそうだ。

プレフィックスルーティングもだるいし、viewだけディレクトリ切って各権限毎に振り分ける場合とかどうしたらいいんだべ?

今回は諦めてctpファイルを調整することにします。

2013年3月16日土曜日

TX-NR616 HDMI接続したPCの画面が映らない

今日、ふとPCから接続しているテレビに映像を出そうとしたら、映らなくなっていることを思い出して、いろいろいじってみた。

構成はこんな感じ

■PC
・グラボはAMD
 →SAPPHIRE ULTIMATE HD 7750 1GB GDDR5
・モニターへはDVI

|HDMI

■TX-NR616

|HDMI

■BRAVIA

音は出るんだけど、映像が出ない。
出ないけどBRAVIAはずっとシーンセレクトをしてる。

ということは、出力されている映像がおかしいということで、Catalystの設定をいじくりまわしてみる。

結果として、出力されたのは以下の項目。

マイデジタルフラットパネル>ピクセル形式 で、
現在のディスプレイを「TX-NR616」にして、色ピクセル形式を「YCbCr 4:2:2 ピクセル形式」へ変更したら直った。

なんか、TX-NR616は癖があるなー。
PS3の時もいじらないと表示されなかったし。

設定が終われば特に気になんないからいいけど。

2013年2月24日日曜日

【Typefi】自動組版 その1

ニッチなんだよね

自動組版という狭い業界に住んでいます。多分、見に来ていただいた方は同業者さんになるのでしょう。

私が所属する組織では自動組版にTypefiというソフトを利用しています。
InDesignのプラグインとして稼働し、inddやindbファイルを出力することが可能です。
ですので、InDesignが対応しているファイル形式を出力することが可能です。

日本では導入しているところが少なく、残念ながら技術交流などがありません。
残念で仕方ありませんので、この場を借りてそういった思いを発散することで日本ユーザーも増えればいーなーとか思っています。

Typefiというソフト自体は、グローバル展開を行なっていて世界中にユーザーがいるそうです。
詳細はTypefi社のホームページで。

聞いた話によると、InDesign CS5で追加された段抜き機能はTypefiのシステムからスピンオフしたそうですよ?

Typefiの特徴

InDesignでテンプレート

こいつの特徴ですが何がすばらしいってなんと、InDesignで自動組版のテンプレートが作成できちゃう!
ということは、テンプレートに関して言えば既存のDTPオペレーターに任せることが可能です。いろいろと制約はありますが。
システム的にタチ位置がどうだとか、ツメがどうだとか、ランニングヘッダーがどうだとか面倒だと思っているそこのアナタ!一見の価値はあるかもです。

拡張可能

プラグインとして稼働するTypefiですが、javascript等での拡張が可能です。
ページ単位や見開き単位でスクリプトを走らせることで、細かな調整が可能になります。
他のプラグインも同時に走らせることも可能かも?

多言語実績

私のところでは20言語ほど行なっていますが、InDesignで可能な言語は対応可能の模様です。
アラビア語などの右流れをやりたいなーと思い、CS6で対応したのでワクワクしてます。

ワード組版

私は使ってませんが、ワードから組版が可能だそうです。
あるのに使わないとか宝の持ち腐れ?

WEB API

組版を行うマシンでWebサーバーが稼働することで自動組版の受付を行なっています。
ただし、独自で拡張可能なようにRESTでのI/Oが可能になっています。

デメリット

やはりあります。ここでは書きませんが、魔法のように自動組版が行えるわけではありません。
もともとはArbortextPrintPublisher(旧名称:3B2)を使っていましたが、やはり精度では追いつけていない所もあります。
こういったものに、トレードオフはつきものですね。

今回はこんなトコロまで。

次回はもうちょっと突っ込んでいきます。











【XSLT】入門編 その1

XSLTはじめます

一年ぶりに更新します。
ヤル気が出てきて自分でもビックリ。

さて、XSLTについて入門として触れていこうかなーとおもいます。

XSLTってなによ?!っていう方は・・・ぐぐってからお越しください、というのもなんですので、wikipediaでも御覧ください。

簡単にいうと、CSSと並ぶhtml(xml)用のスタイルシートです。
見に来てくださった皆様はきっともう知ってらっしゃいますよね?(という体で・・・)

いきなり2.0勧められてもわかんねーよ!っていう方がおられましたらすいませんでした。

私はXSLTは実務で使用しています。
自分なりの答えなので、間違いがありましてもご容赦ください。
(指摘していただけると幸いです)

ちなみにこの入門も2.0準拠で話を進めたいとおもいます。

だってみつからなかったんだもん

ネット、本ともにXSLTに関する資料は少なくはないのですが、実務での使い方や理想的な組み方について触れている資料は、少なくとも自分が探した範囲ではありませんでした。

多分、帳簿計算、データ抽出やデータトリミングに使われることが多く、変換という観点でのデータ全体の再利用方法のアプローチは、DITAなどのドキュメントデータレベルでしか使用されることが少ないのが原因ではないかなーと思っています。

しかも、DITAやDocBookなどの情報は日本語で解説しているページはあまりありません。
まーすごく日本人的だなーとか思っちゃいます。

入門編 その1

さて、入門するにあたって重要なキーワードが3つあります。
  1. データモデル
  2. コンテキストアイテム(旧名称:カレントノード)
  3. ロケーションパス
はい、出ました。
この3つがわかればXSLTが理解できたも同然です。
けっこうマジな話本当です。

では詳細に入っていこうと思います。

1.データモデル

他のプログラム言語にもあるように、XSLTにもデータ型が決まっています。
1.0と1.1は変わらなかったはずですが、2.0になった時に大きく変更されました。

それがこれだ!
頭痛い系ですね。
W3Cにあるものそのまま持ってきただけです。

全体が理解できていると素晴らしいですが、本当に必要なのはこの部分だけです。
XSLTにおいて、このnode群が全てと言っても過言ではありません。

これを1つずつ見て行きたいと思います。
ちなみに緑色のところは関係ありません。

node:ノード

下記の種類を内包する抽象的なデータ型です。
nodeというデータ型がデータ上に存在するわけではありません。

attribute:属性ノード

属性ですね。属性値とは別物ですので注意してください。
hogehoge=""と表記されます。

comment:コメントノード

コメントですね。
<!-- -->という表記になります。

document:ドキュメントノード・ルートノード

ルートノードと呼ばれることもあります。
多くは対象の入力処理ファイル(xml)のことを指します。

element:要素ノード

要素です。
<div></div>または<div />という表記になります。

processing-instraction:処理命令ノード

これがちょっとわかりにくいですが、多くは先頭に書かれている宣言に使われています。
<?xml version="1.0" encoding="UTF-8"?>

ちなみに、phpの宣言も同じように扱えます。
<?php hogehoge ?>

text:テキストノード

実際の文章データです。
これは、>hogehoge<のようにタグで囲われている部分を指しています。


xml上で再現するとこんな感じでしょうか?
<?xml version="1.0" encoding="UTF-8"?>
<!-- コメント -->
<書籍 出版日="2013-02-24">あまぞん</書籍>

document

<?processing-instraction ?>
<!-- comment -->
<element attribute="ここはtextではありません">text</element>


データモデルを理解しようと進めていくと、あることに気が付きます。
そう、変数がありません。
XSLTではこのデータモデルに載っていないモデルを扱うことはできません。
通常のDOMなどを使用すると、このへんの扱いもコントロールすることが可能ですが、XSLTでは不可能です。

詳細は省きますが、処理を行う際に変換元のxmlも変換するためのXSLTもプロセッサによってパースされてしまい、そのタイミングで既に変数が消滅しているからということになります。

それも合わせて、XSLTでデータを扱う際にはデータモデルに扱いたいデータ型があるかどうかが大前提になります。


2.コンテキストアイテム


XSLTはデータ駆動であり、処理対象であるxmlにそって変換が行われるわけですが、処理されている現在のアイテム(ノード)位置をコンテキストアイテムと言います。

間違えちゃうから気をつけて!

そもそもコンテキストアイテムという言葉は2.0から使用されるようになりました。
じつは、それまではカレントノードと呼ばれていました。
なぜ名称が変更されたかというと、データモデルが増加し、モデルの頂点がItemとなったためです。
そのため使用する関数などにcurrentという名残があります。

カレントアイテムにならなかったのは、データ型がノードだけではなくなり、必ずしも処理対象のxml上に存在するわけではなくなったためです。
最初はピンとこないとおもいますので、データモデルが大きく変更されたためとおぼえておいてください。

XSLTの2.0とそれ以前の資料が混ざってしまい、コンテキストだのカレントだの書かれていますが言ってしまえば”ほぼイコール”ということになります。

以下では全てコンテキストアイテムに統一します。

実際の変換を行なってみると、厳密な型管理を行うにはそれなりに仕込みをしなければなりませんので、実際にはノード群を扱うことが殆どになると思います。


さて、じゃあ結局”コンテキストアイテム”とはなんなんだという話になるんですが、処理上での現在位置ということになります。

表現の一例を出してみます。

正しい表現

  • コンテキストアイテムはノード
  • コンテキストアイテムは要素、コンテキストアイテムは要素ノード、コンテキストアイテムはdiv要素
  • コンテキストアイテムはコメント、コンテキストアイテムはコメントノード

誤った表現

  • コンテキストアイテムはdiv→データモデルがどれなのかわかりません。
  • コンテキストアイテムはxsl:template要素→変換対象のxml上のアイテムしかコンテキストアイテムになりえません。
XSLTではコンテキストアイテム(現在位置)から何をどうしたいのか、という記述の塊になります。
なので、すべての基準がコンテキストアイテムになる、ということになります。

コンテキストアイテムを変更できるXSLT要素は限られており、コンテキストアイテムの変更は柔軟にはできません。
変更方法については、今回は飛ばします。

3.ロケーションパス

ロケーションパスは、コンテキストアイテムからの相対的な位置を表します。
じゃあ、なんの位置を表すんだよ?ということになると思いますが、それは場所や用途によって変化します。