LoginSignup
6
5

More than 3 years have passed since last update.

atomフィードをXSLTで加工してiframeで埋める

Last updated at Posted at 2018-05-10

screenshot 2018-05-10 10.04.52.png

teratail「ホームページの新着情報部分だけをxmlで書いて読み込みたい」でディスカッションしてたんですが、そこで次の欲求が湧いてきました。

  • atomフィードやRSSフィードと同じ内容を新着情報としてHTMLに埋め込みたい
  • ただし、サーバーサイドのコードを書いてHTMLを生成するのは面倒くさい
  • jqueryのajaxとかでatomの内容を取得・加工してDOMに吊るすのも少し面倒くさい

XSLTを使えばxmlの内容をブラウザ側でhtmlに変換でき、それをiframeで埋めれば楽に実現できるのではないかと思い、実際にやってみたので書き留めます。

XSLTとは

XSLTとはXML文書を別のフォーマットのXML文書に変換するための言語です。
eXtensible Stylesheet Language Transformationsの略らしいです。
今回はこれをXMLからHTMLに翻訳するために仕様します。

参考記事: XMLをXSLTを使ってHTML文書にする

最小構成のダミーatomフィード

最小限のデータのみ持ったatomフィードを作りたいです。
必須要素は id, title, updated の3つですが、更新履歴として記事の概要を付けたいので entry には summary も付けることにします。
最終的に以下のようなatomフィードを用意しました。

<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>http://example.com/</id>
  <title>sample latest updates</title>
  <updated>2018-05-09T00:00:00+09:00</updated>
  <entry>
      <id>http://example.com/post6.html</id>
      <title>Title of article 6</title>
      <updated>2018-05-12T00:00:00+09:00</updated>
      <summary>Summary of article 6</summary>
  </entry>
  <entry>
      <id>http://example.com/post5.html</id>
      <title>Title of article 5</title>
      <updated>2018-05-11T00:00:00+09:00</updated>
      <summary>Summary of article 5</summary>
  </entry>
  <!-- 中略 -->
</feed>

参考記事: RSS、atomの仕様をまとめる
参考記事: 最小限のAtomフォーマット

atom.xmlをインクルードする別のxmlファイルを作る

XSLTの定義ファイルがfoobar.xslだとして、xmlファイルにXSLTを適用した結果をブラウザに表示するには、xmlファイル内部に次の処理命令を書けば良いです。

<?xml-stylesheet type="text/xsl" href="foobar.xsl"?>

ただしatom.xmlなどのフィードは自動生成されることも多く、「atom.xmlをて編集して一行付け足す」という手順は良手とは思えません。
なんかいい方法ないかなーと探してみたところ StackOverflow: Apply XSL to External XML に良さげな方法を発見しました。
曰く、次のようにすればatom.xmlをインクルードする別のxmlファイルを作れるそうです。

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="wrapper.xsl"?>
<!DOCTYPE wrapper [
  <!ENTITY content SYSTEM "atom.xml">
]>
<wrapper>
  &content;
</wrapper>

これでatom.xmlは一切変更することなく、その内容にXSLTを適用することが可能になりました。やったぜ!

変換規則の定義

XSLTの内容は次のようにしました。

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:a="http://www.w3.org/2005/Atom">

  <xsl:output method="html" encoding="UTF-8"/>

  <xsl:template match="text()"/>

  <xsl:template match="a:feed">
    <html>
      <head>
        <title>
          <xsl:value-of select="a:title"/>
        </title>
        <link rel="stylesheet" href="wrapper.css"/>
      </head>
      <body>
        <h1>
          <xsl:value-of select="a:title"/>
        </h1>
        <ul>
          <xsl:apply-templates/>
        </ul>
      </body>
    </html>
  </xsl:template> 

  <xsl:template match="a:entry">
    <li>
      <xsl:element name="a">
          <xsl:attribute name="href">
              <xsl:value-of select="a:id"/>
          </xsl:attribute>
          <xsl:value-of select="a:title"/>
      </xsl:element>
      :
      <xsl:value-of select="a:summary"/>
      (<xsl:value-of select="substring(a:updated, 1, 10)"/>)
    </li>
  </xsl:template> 

</xsl:stylesheet>

注意点としては、atom.xmlの方でhttp://www.w3.org/2005/Atomネームスペースで書いているので、xslファイルの方でマッチさせるときも同じネームスペースでマッチするようprefixa:を定義する必要があるということです。
これで30分くらい悩みました。

結果的にできたもの

screenshot 2018-05-10 10.04.52.png

出来たxmlファイルをブラウザで表示するとhtmlファイルのように表示され、iframeで他のhtmlファイルに埋め込んでも正常に動きました。

デモ: https://set0gut1.github.io/atom-xslt-example/
全ソース: https://github.com/set0gut1/atom-xslt-example

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5