agenda 2003-09(上旬)

document(絶対URI) の例 - RSSの再利用(XSLT 1.0)

最終更新
2003-09-12T20:35:07+09:00

document関数の例の第一回は、最も単純なdocument(絶対URI) というパターンの例を、RSSの再利用という形で紹介します。

document(絶対URI)の場合、そのURIであらわされるリソースのXMLノードツリーのルートノードのみを含むノード集合が返されます。それだけですので別に例示する程の話でもありませんが、ちょうどagendaの最新版を整形しているXSLTスタイルシートで使用しているので急遽書いてみることにしました。さて:

Weblogの最新版では、最新の記事一つだけを紹介し、それ以前の数点は「最近の記事一覧」としてアンカーと概要のみを掲載することにしました。dive into markの「older posts」の真似です。

「最近の記事一覧」のアンカーリストは、RSS文書から引っ張ってきたデータをHTMLに変換する形で、XSLT(スタイルシートとプロセッサ)に行わせます。

<xsl:template name="olderPosts">

<xsl:variable name="rss.nodeset"
  select="document('http://members.jcom.home.ne.jp/jintrick/Personal/putdata.xml')" />
<dl>
  <xsl:for-each
    select="$rss.nodeset/descendant::rss:item[string(child::slash:section) = 'agenda']">
    <dt>
      <a href="{@rdf:about}">
        <xsl:value-of select="string(child::rss:title)" />
      </a>
    </dt>
    <dd>
      <dl>
        <dt>更新日時</dt>
        <dd>
          <xsl:value-of select="string(child::dc:date)" />
        </dd>
        <dt>概要</dt>
        <dd>
          <xsl:value-of select="string(child::rss:description)" />
        </dd>
      </dl>
    </dd>
  </xsl:for-each>
</dl>

</xsl:template>

これを任意の位置でcall-templateするだけです。というわけで、XSLTの話題として面白くもなんともありませんというか、RSSの再利用の話ですかこれは。他のサブサイトのホームページで、最近更新した文書をこのような形で紹介すると便利かもしれません。

他に、document関数を利用して、サイト全体のRSSをサブサイトのRSSに分割したりできます。その場合、サブサイトを識別する何らかの要素がRSS文書の各item要素内に必要です。前述の例では、サイト「Personnel」の更新情報としてのRSSの中に、サブサイト「agenda」の更新情報が含まれており、サブサイト「agenda」の更新アイテム(主語)については、slash dotモジュールを利用して、slash:section要素(述語)にagendaというテキストノード(目的語)を入れて識別しています。

document関数の概要(XSLT1.0)

最終更新
2003-09-11T15:19:38+09:00

XSLT1.0 のdocument関数の定義をはっきりさせる試み。

仕様書のdocument関数の説明が曖昧で分かりづらいと思われたので、適当に意訳してみました。間違った解説、不十分な解説が多いのも理由です。

尚、ノード集合は {} (一対のカーリブラケット)で表記し、各ノードはその中にカンマで区切って列挙しています。

document(ノード集合) の場合

  • あるdocument関数 が、唯一つの引数 A を持ち、A がノード集合 { a1, a2, .. am } である場合、その戻り値は、A に含まれる各ノード an (n = 1, 2, .. m) について、an の文字列値を第一引数とし、an のみ含むノード集合を第二引数にもつ document関数、即ち、 document(string({ an }), { an }) (n = 1, 2, .. m) の結果の和集合になる。

もう少し短くしますと:

  • あるdocument関数 が、唯一つの引数 A を持ち、A がノード集合 { a1, a2, .. am } であるならば、その戻り値は、document(string({ an }), { an }) (n = 1, 2, .. m) の戻り値の和集合になる。

因みにこのケースについてきちんと説明している解説を見たことがありません。

docuemnt(ノード集合)の例に続きます。

document(ノード集合, ノード集合) の場合

  • あるdocument関数が二つの引数 A, B を持ち、A がノード集合 { a1, a2, .. am } であり、B がノード集合 { b1, b2, .. } であるならば、その戻り値は、document(string({ an }), { b1 }) (n = 1, 2, .. m) の結果の和集合となる。

document(文字列) の場合

document(絶対URI) の場合

  • あるdocument関数が唯一つの引数 A を持ち、A が絶対URIを表す文字列であったなら、その戻り値は、ノード集合 { B } になる。但し B は、絶対URI A が識別するリソースのXMLツリーのルートノードであると定義する。

docuemnt(絶対URI)の例に続きます。

document(相対URI) の場合

  • あるdocument関数が唯一つの引数 A を持ち、A が相対URIを表す文字列であったなら、その戻り値は、ノード集合 { B } になる。但し B は、そのdocument関数を呼び出したXSLTの要素が持つBase URIを基底として、相対URI A を絶対URI A' に解決したときの A' が識別するリソースのXMLツリーのルートノードであると定義する。

document(文字列, ノード集合) の場合

document(絶対URI, ノード集合) の場合

  • あるdocument関数が二つの引数 A, B を持ち、A が絶対URIを表す文字列であったなら、その戻り値は、ノード集合 { C } になる。但し C は、 絶対URI A が識別するリソースのXMLツリーのルートノードであると定義する。 URIの解決に不要である為 B は無視される。

document(相対URI, ノード集合) の場合

  • あるdocument関数が二つの引数 A, B を持ち、A が相対URIを表す文字列、B がノード集合 { b1, b2, .. } であったなら、その戻り値は、ノード集合 { C } になる。但し C は、ノード集合 B における ノード b1 のBase URIを基底として、A を絶対URI A' に解決したときの A' が識別するリソースのXMLツリーのルートノードであると定義する。

document(文字列でもノード集合でもないデータ型, ノード集合?) の場合

  • あるdocument関数 document(A, B?) の第一引数 A が、文字列でもノード集合でもないならば、その戻り値は、document(string(A), B?) の結果と同じである。

私はまずこの方法は使いません。最初からstring関数で文字列に変換しておきます。ややこしいからエラーにしてしまえば良いのに。

さて

それぞれの例については後ほど(長すぎるので)。

名前空間を汚さない再帰処理(JScript)

最終更新
2003-09-01T18:25:49+09:00

DOMインターフェイス等を使ってXMLノードツリーのちょっとした検索をする場合に、無駄な変数の宣言を避け、その検索にのみ使用する変数を全て、その検索処理を行う関数の外部からは参照できない局所変数にし、さらにその関数自体も無名関数を使ってみようという試みです。

簡便化の為、XMLノードツリーは擬似的に単なる配列(Arrayオブジェクト)にして例示します。

var ary = [0, [1, 1, [2, 'it', [3,3]]]];

このような配列内において、唯一String型になっているアイテムを変数itに代入することを目的とします。更に、変数it以外は同じスコープから参照不可能になるように工夫します。

var it = function(_ary){
    for(var i = 0, obj, len = _ary.length; i < len; i++)
    {
        obj = _ary[i];
        
        switch(obj.constructor)
        {
            case String :
                return obj;
                break;
            case Array  :
                return arguments.callee(obj);
                break;
            default     :
                break;
        }
    }
}(ary);

alert(it); // it

変数itに無名関数の戻り値を代入し、その無名関数の中で自分自身(arguments.callee)を呼び出して再帰処理を行っています。

この例における配列はノードリストに、また、配列のアイテムはノードに、そしてconstructorプロパティはnodeType等判別に使用したいプロパティ等に置き換えて使用します。その際にはもう少しややこしくなりますが、考え方は同じです。