Excel 2007 XML を OASIS コード・リストに変換する

Genericode の処理方法

OASIS 仕様の 1 つである Genericode は、コード・リストまたは権限リストをXML にエンコードするための XML 語彙です。これらのリストを作成および保守するビジネス・ユーザーは、一般に Microsoft® Office のソリューションに慣れてはいても、XML 技術には堪能ではありません。この記事では、コード・リストの作成および保守に Microsoft Office Excel® 2007 スプレッドシートを使用する方法を説明し、さらに XSLT を使用してそのスプレッドシートをオンライン・フォームなどのアプリケーションからも容易に利用できる標準準拠の Genericode に変換する方法を説明します。

Betty Harvey, Information Architect, Electronic Commerce Connection, Inc.

Betty Harvey は、Electronic Commerce Connection, Inc. の代表取締役を務めています。彼女は多数の政府機関および企業での構造化情報への移行計画および実行に関与してきました。現在は ebXML イニシアチブに参加し、『Professional ebXML Foundations』(Wrox、2001年) を共同で執筆した他、活発に執筆活動を行っています。また、首都ワシントンで SGML/XML Users Group を立ち上げ、このグループをまとめている傍ら、XML Guild のメンバーでもあります。Betty への連絡先は harvey@eccnet.com です。



2011年 1月 11日

Genericode は、OASIS (Organization for the Advancement of Structured Information Standards) 仕様 UBL (Universal Business Language) 技術委員会から生まれました (「参考文献」を参照)。当初、UBL が従っていたのは、UN/CEFACT (United Nations Centre for Trade Facilitation and Electronic Business) コア構成要素技術仕様 (「参考文献」にリンクを記載) です。この仕様では、列挙型を使用して通貨コードや国名コードなどのコード・リストを W3C の Schema に直接埋め込んでいました。

よく使われる頭文字語

  • W3C: World Wide Web Consortium
  • XML: Extensible Markup Language
  • XSLT: Extensible Stylesheet Language Transformation

UBL コミュニティーはまもなくして、コード・リストが頻繁に変更されることに気付きました。リストを直接スキーマに直接埋め込むという方法は、検証には楽でしたが、リスト内のコードが変更された場合にはスキーマを更新しなければなりません。取引相手が複数いるとなると、更新したスキーマを扱うのはロジスティクスの悪夢となり得ます。さらに、スキーマを再コンパイルして、更新後のスキーマを基にデータベースを再初期化しなければならない製品も数多くあります。

UBL 技術委員会は、コードが変更されるたびにスキーマを更新しなければならないという問題を解消するための抽象化層として、Genericode を開発しました (詳しくは「参考文献」のリンクを参照)。また、Schematron などの他の検証手法を、コードを検証する検証層として使用することができます。Genericode は UBL よりも幅広く支持される結果となったため、OASIS は Genericode 仕様を管理する新たな技術委員会を発足することにしました。

この記事では、Microsoft Office Excel 2007 スプレッドシートを使ってコード・リストを作成する方法を説明し、さらに XSLT を使用してコード・リストを Excel スプレッドシートの形式から Genericode に変換する方法を説明します。

Office Excel 2007 形式のコード・リスト

記事では Genericode への変換を具体的に取り上げますが、その概念は、他のタイプの Excel 文書や XML 語彙にも一般論として当てはめることができます。例えば、私は Microsoft Office Excel 2003 への変換、またはこの形式からの変換を数多く行ってきましたが、そのなかで、この変換プロセスがかなり直接的なものであることに気付きました。Office Excel 2003 形式から XML 形式に変換する場合は、スプレッドシートを Office Excel 2003 XML に保存するといった具合です。私が作成した変換の 1 つは、W3C のスキーマからスプレッドシートへの変換で、スキーマ分析スプレッドシートが作成されるものです。Excel 形式にすることで、技術系ではない人々でもスキーマ・コンポーネント間の関係、そしてスキーマ・コンポーネントそれぞれの定義を容易に理解できるようになります。

私が作成したもう 1 つの使える変換は、Office Excel 2003 XML から Genericode への変換で、これは本番環境でも適切に動作します。コード・リストには空のセルがある場合が多いですが、Office Excel 2003 XML で空白になっているセルは、この変換では XML には出力されませんでした。また、行を分析してどのセルが省略されているかを自動的に判断する簡単な方法もありませんでした。この問題は、Office Excel 2003 と Office Excel 2007 の両方に当てはまります。ただし、Office Excel 2007 には、セルが空白になる場合を論理的に解明する機能が用意されています。

この記事ではサンプルとして、図 1 に示す単純な構造を使用します。これは、Excel コード・リストです。

図 1. サンプル Excel コード・リスト
CodeList 名、CodeValue 名 (列のラベル)、そして個々の値からなるサンプル Excel コード・リストのスクリーン・キャプチャー

OASIS Genericode と Office Excel 2007 の構造

変換プロジェクトを開始する前には、必ず最初の構造と最終的な構造を理解しておかなければなりません。Genericode は複雑になることもありますが、コード・リスト全体の 98 パーセントは比較的理解しやすいものです。単純なコード・リストは、以下の 3 つのセクションに分けられます。

  • ID
  • 列の仕様
  • コード・リストのデータ

図 2 に、Genericode の XML スキーマを図解します。CodeList 文書 (型: gc:CodeListDocument) には、その文書を記述する複数の属性があります。gc:DocumentHeader に含まれるのは、Annotation (型: gc:Annotation) と Identification (型: gc:Identification) です。gc:ColumnSetChoice には ColumnSet (型: gc:ColumnSet) と ColumnSetRef (型: gc:ColumnSetRef) が含まれ、gc:OuterCodeListChoice には gc:SimpleCodeListSequence と SimpleCodeList (型: gc:SimpleCodeList) が含まれます。

図 2. Genericode の構造
Genericode の構造を示す図

一方、Office Excel 2007 XML は Genericode コードほどには単純ではありません。実のところ、その構造はかなり風変わりです。XLSX ファイルは実際には ZIP ファイルであり、複数のファイルが含まれます。

  • ルートには以下のディレクトリーがあります。
    • _rels
    • docProps
    • xl
      • _rels
      • printerSettings
      • theme
      • worksheets

それぞれのディレクトリーごとに、数多くの XML ファイルが保管されています。変換の際には、このすべてのファイルやそれぞれの目的を考える必要はありません。これらのファイルのうちのいくつかは、Excel が Excel アプリケーションを制御するために内部で使用するファイルだからです。この記事での変換に関与するファイルとしては、以下のものがあります。

  • /docProps/app.xml: 組織の情報が含まれます。
  • /docProps/core.xml: 時刻や作成者などのメタデータが含まれます。
  • /xl/worksheets/sheet1.xml: データへのマッピングが含まれます。
  • /xl/sharedStrings.xml: 実際のデータが含まれます。

これらのファイルにはロジックがありますが、一見しただけでは、そのロジックはわかりません。


Excel データとのマッピング

sharedStrings.xml ファイルと sheet1.xml ファイルは連携しています。まず、図 1 の Excel コード・リストの sharedStrings.xml ファイルについて見ていきましょう。リスト 1 に、この XML ファイルのファイル構造を記載します。

リスト 1. sharedStrings.xml のファイル構造
<sst>
     <si>
          <t>My Data 25</t>
     </si>
     <si>
          <t>My Data 10</t>
     </si>
     ...
</sst>

興味深いことに、sharedStrings.xml ファイルでのデータの組み込み方には論理的順序があるようには見えません。このファイルは基本的に Excel スプレッドシートのすべてのセルを一様に記述しているだけです。

データの保管場所は、以下のようにセルのデータ型に応じて異なります。

  • 文字列データ: sharedStrings.xml ファイルに配置され、このファイル内で検索されます。
  • 整数データ: sheet1.xml ファイルに配置されます。
  • 式データ: sheet1.xml ファイルに配置されます。

注: 式データをコード・リストに含めるというようなケースはまず考えられません。

sheet1.xml はデータへのマッピングを提供するファイルです。sheet1.xml のファイル構造は図 3 のようになっています (図 3テキストで表現したものを見るには、ここをクリックしてください)。

図 3. sheet1.xml の構造
sheet1.xml の構造を示す図

データそのものは <row> 要素に含められます。表 1 に、sheet1.xml ファイルの要素を記載します。

表 1. sheet1.xml の要素および属性
要素または属性説明
rowExcel スプレッドシートの行の開始
@r行番号
@spans行に含まれる列の数。最初の数値が開始列で、2 番目の数値が終了列です。
cセルに関する情報
@rセルの物理的な位置。例えば、B10 は列 B、行 10 の位置となります。
@s="1"セルの実際の値。この属性が指定されている場合、sharedStrings.xml ファイル内を検索する必要はありません。
@tデータ型。例えば、s は文字列を表します。@t が指定されている場合は、sharedStrings.xml ファイルで <v> 要素の値が検索されます。
v<si> 要素の番号に 1 を足した数値が含まれます。これは、sharedStrings.xml ファイル内で実際のデータが配置されている位置です。

要素に含まれる値は、sharedStrings.xml ファイル内にある <si> 要素の XPath 番号に 1 を加えた値です。t 属性値は s に設定されます。s は、文字列の値を表します。

2 番目と 3 番目のセルには t 属性がありません。t 属性がないということは、データがこのファイルに含まれていることを意味します。計算が行われるフィールドの場合、その先頭文字としてプラス記号 (+) が組み込まれるので、整数と区別することができます。


XSLT の開発

Office Excel 2007 には複数のファイルがあること、そして変換手法はさまざまな方法で開発できることから、基準とする XML ファイルを選択する必要があります。sheet1.xml には、データへのマッピングが含まれていることから、ここでは sheet1.xml ファイルを基準 XML ファイルとして使うことにしました。データ・ファイル (sharedStrings.xml) は静的なので、このファイルからインテリジェントなナビゲーションを推測するのは難しい話です。前述のとおり、Genericode には 3 つの主要な情報コンテナーがあるので、各コンテナーの変換について見ていきましょう。

グローバル変数

検索は、複数のファイルで行わなければなりません。そこで、さまざまなファイルの完全パス名を使用する代わりに、グローバル変数を作成すると、検索が容易になるとともに、コードが読みやすくなります。

以下のパラメーターが、XML ファイルのルート・ディレクトリーを設定します。XProc パイプラインやバッチ・ジョブを使用して複数のコード・リストを変換する場合には、このパラメーターの値をそのプロセスに送信することができます。

<xsl:param name="ExcelRoot">MyCodelist</xsl:param>

以下に記載する変数を使用して、情報が含まれるファイルの完全パスおよびファイル名を取得します。

<xsl:variable name=”DataFile”>
  <xsl:value-of select=”$ExcelRoot”/>/xl/sharedStrings.xml</xsl:variable>

ルート・テンプレート

変換の出発点となるのは、<worksheet> テンプレートです。リスト 2<worksheet> 要素のテンプレートの一例を記載します。基本的に、この最初のテンプレートは各セクションの変換を呼び出します。最初に変換するファイルは、sheet1.xml です。名前空間接頭辞は「Excel」であり (必要に応じて変更しても構いません)、ルート要素は <worksheet> です。したがって、このテンプレートは Excel:worksheet との突き合わせを行うことに注意してください。

リスト 2. 最初のテンプレート
<xsl:template match="Excel:worksheet">
   <CodeList xmlns="http://docs.oasis-open.org/codelist/ns/genericode/1.0/"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:era="http://archives.gov/era/schema"
         xsi:schemaLocation="http://docs.oasis-open.org/codelist/ns/genericode/1.0/
         http://docs.oasis-open.org/codelist/cs-genericode-1.0/xsd/genericode.xsd">

         <xsl:call-template name="commentBlock"/>
         <xsl:call-template name="identificationBlock"/>
         <xsl:call-template name="createColumnSet"/>
         <xsl:apply-templates/>
        </CodeList>
    </xsl:template>

Excel 固有の不要なデータを削除するために、デフォルトのテンプレートも作成する必要があります。

<xsl:template match=”*”/>

この記事では、コード・リストの本体 (<SimpleCodeList>) に専念します。このロジックがあれば、他のセクションを開発するのは簡単だからです。Excel コード・リストのテンプレートに関しては、それぞれの組織に独自の手法があります。


<SimpleCodeList> および <Row> 出力の作成

<sheetData> 要素は、<worksheet> 要素の直接の子です。<SimpleCodeList> 要素は、この <sheetData> 要素から派生され、<Row> 要素は、<row> 要素から派生されます。このとおり、単純明快な仕組みです。リスト 3 に、<SimpleCodeList> 要素と <Row> 要素を作成する XML を記載します。

リスト 3. <SimpleCodeList> および <Row> の作成
   <xsl:template match="Excel:sheetData">
        <SimpleCodeList>
            <xsl:apply-templates/>
        </SimpleCodeList>
    </xsl:template>

    <xsl:template match="Excel:row">
        <Row>
            <xsl:apply-templates/>
        </Row>
    </xsl:template>

列参照を作成する

Genericode では、そこに含まれるすべてのエントリーに列参照を使用することを要件としています。列参照情報は、<ColumnSet> 要素内に取り込まれます。<Identification> および <ColumnSet> エントリーは、それぞれの組織がそのコード・リストを Excel 形式で保持するために使用するテンプレートによって異なるため、これらのエントリーの作成方法はここでは説明しません。ただし、<Value> 要素に @ColumnRef 情報を取り込むには、列参照情報が必要です。

各見出しに対応する変数は、手動で設定します。これらの変数を設定するには、おそらくもっと洗練されたやり方があると思いますが、この方法でも上手くいきます。見出しの変数の次は、列の変数を作成します。リスト 4 では、セル A2 の <v> 要素の値を選択しています。番号付けは 0 から始まるため、<v> の値には 1 を加算しなければならないことに注意してください。

リスト 4. 列参照の作成
<xsl:variable name="ColumnALocation">
   <xsl:value-of select=
    "//Excel:worksheet/Excel:sheetData[1]/Excel:row[2]/Excel:c[1]/Excel:v + 1"
 />

この列参照から、セルに含まれる実際の値を取得する必要があります (リスト 5 を参照)。この例では、列の位置がヌルではないことを確認するためのテストを行います。列の位置の値がヌルでなければ、sharedStrings.xml ファイルで検索を行います。このファイルでは、位置の軸 (position()) が sheet1.xml の <v> 要素に含まれる値に相当します。この変数は、後で @ColumnRef 属性を判断するために使用します。

リスト 5. セルに含まれる実際の値の取得
<xsl:variable name="Column-A">
    <xsl:choose>
        <xsl:when test="$ColumnALocation = ''"/>
        <xsl:otherwise>
            <xsl:value-of
                select="document($DataFile)/Excel:sst/Excel:si[position() =
            $ColumnALocation]"
            />
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>

<Value> 要素の作成

図 1 をもう一度見てみると、列 A1 の値は a1 となっていることがわかります。したがって、Genericode による表現は以下のようにしなければなりません。

<Value ColumnRef="ColumnA">
    <SimpleValue>a1</SimpleValue> 
</Value>

<c> 要素の @r 属性に含まれるのはセルの座標です。例えば、A2 とある場合、これは列 A の行 2 を表します。この例では、列の見出しは A2B2C2 となっていますが、タイトルと列の見出しがそれぞれどのセルにあるのかを知る必要があります。

そこで、以下の 3 つの変数を設定します。

  • column: 列番号。例えば、B は 2 番目の列を表します。この情報は、@r の値に含まれます。
  • dataLoc: データの位置。これは、sharedStrings.xml ファイル内でデータが置かれている位置を示す、XPath + 1 の位置です。
  • cellValue: セルに含まれる実際のデータ。この変数は、sharedStrings.xml ファイルを直接検索して設定します。

変数を設定した後、データの取り込みを開始します。このプロセスの後半では、@ColumnRef 属性に値を取り込みます。これは同じテンプレートで行うこともできますが、ここでは、2 つ目のテンプレートを作成し、そこに column 変数を送信して列の名前を検索することにします (リスト 6 を参照)。

リスト 6. サンプル <c> テンプレート
<xsl:template match="Excel:c">
    <xsl:variable name="column"><xsl:value-of select="substring(@r, 1, 1)"/>
    </xsl:variable>
    <xsl:variable name="dataLoc"><xsl:value-of select="number(Excel:v) + 1"/>
    </xsl:variable>
    <xsl:variable name="cellValue">
       <xsl:value-of 
         select="document($DataFile)/Excel:sst/Excel:si[position() = $dataLoc]"/>
    </xsl:variable>
   <xsl:choose>
      <xsl:when test="Excel:v">
         <Value>
            <xsl:attribute name="ColumnRef">
                 <xsl:call-template name="getColref">
                    <xsl:with-param name="column"><xsl:value-of select="$column"/>
                    </xsl:with-param>
                  </xsl:call-template>
                 </xsl:attribute>
                <SimpleValue><xsl:value-of select="$cellValue"/></SimpleValue>
              </Value>
           </xsl:when>
        <xsl:otherwise/>
    </xsl:choose>
</xsl:template>

列参照名

パズルを完成させる最後のピースは、列名の取得です。コード・リストに多数の列があるのではない限り、リスト 7 の方法で十分対処することができます。ほとんどのコード・リストでの列数は、2 列から 5 列といったところです。

リスト 7. 列参照の作成
  <xsl:template name="getColref">
        <xsl:param name="column"/>
        <xsl:choose>
            <xsl:when test="$column = 'A'">
                <xsl:value-of select="translate($Column-A, ' ', '')"/>
            </xsl:when>
            <xsl:when test="$column = 'B'">
                <xsl:value-of select="translate($Column-B, ' ', '')"/>
            </xsl:when>
            <xsl:when test="$column = 'C'">
                <xsl:value-of select="translate($Column-C, ' ', '')"/>
            </xsl:when>
  </xsl:template>

まとめ

傾向として、コード・リストの所有者は Microsoft ツールを使い慣れているビジネス・ユーザーである場合がよくあります。そのようなビジネス・ユーザーであれば、お馴染みの Microsoft ツールでコード・リストのデータを更新し、管理することができます。したがって、XSLT を使用して技術要件をビジネス要件に変換することは、極めて意味のあることです。ほとんど手間もかからずに、ビジネス分野のエキスパートが扱うべき内容と技術上の必要性とを切り分けることのできるワークフローは、効率的かつ実際的な技術ソリューションです。

参考文献

学ぶために

製品や技術を入手するために

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=XML
ArticleID=620300
ArticleTitle=Excel 2007 XML を OASIS コード・リストに変換する
publish-date=01112011