XML 名前空間と XPath と XSLT に与える影響

 

大胆なオバサンジョ
Microsoft Corporation

2002 年 5 月 20 日

これは、Microsoft がサポートする W3C XML テクノロジの微妙な側面を解明するための記事の長い実行が期待される最初の記事です。 コア XML はまだ非常に単純ですが、それを取り巻くテクノロジはますます複雑になり、習得するにはかなりの専門知識が必要なものもあります。 この記事とその他の目的は、さまざまな W3C XML レコメンデーションの情報を、XML ユーザーと開発者が簡単に消化可能なチャンクに分けて使用することです。

このシリーズの最初の記事では、XML 名前空間のよく誤解されるファセットについて説明します。 XML 名前空間は、XPath、XML スキーマ、XSLT、XQuery、SOAP、RDF、DOM、XHTML など、W3C の XML レコメンデーションと作業ドラフトの大部分に不可欠な要素です。 名前空間がどのように機能し、それらに依存する他の多くの W3C テクノロジとどのようにやり取りするかを理解することは、XML を扱うすべてのユーザーにとって非常に重要です。

この記事では、XML 名前空間のインとアウト、および名前空間をサポートする多数の XML テクノロジに対するその影響について説明します。

XML 名前空間の概要

インターネット上の XML の使用が普及するにつれて、ソフトウェア モジュールを組み合わせて再利用する方法と同様に組み合わせて再利用できるマークアップ語彙を作成できることの利点がますます重要になりました。 コインコレクション、プログラム構成ファイル、またはファーストフードレストランメニューを記述するための明確に定義されたマークアップボキャブラリが既に存在する場合、それを再利用することはゼロからデザインするよりも理にかなっています。 複数の既存の語彙を組み合わせて、その部分の合計よりも全体が大きい新しい語彙を作成することも、XML のユーザーが必要とし始めた機能となりました。

しかし、同一のマークアップ、特に XML 要素と属性が、同じドキュメントで終わる異なるセマンティクスを持つ異なるボキャブラリの可能性が問題になりました。 XML の拡張性と、その使用がインターネット全体で既に普及していたという事実は、単に予約された要素または属性名をこの問題の解決策として指定することを排除しました。

W3C XML 名前空間の推奨事項の目的は、異なるマークアップボキャブラリの要素と属性を XML ドキュメント内で明確に識別し、問題を処理せずに組み合わせることができるメカニズムを作成することでした。 XML 名前空間の推奨事項では、処理要件に基づいて XML ドキュメント内のさまざまな項目をパーティション分割する方法が提供されました。これらの項目の名前付け方法に関する過度の制限は適用されません。 たとえば、 という名前<template><output><stylesheet>の要素は、XSLT スタイルシート内で、変換ディレクティブであるか、変換の潜在的な出力であるかに関してあいまいさが存在しない場合に発生する可能性があります。

XML 名前空間は、 UNIFORM Resource Identifier (URI) 参照によって識別される名前のコレクションであり、XML ドキュメントでは要素名と属性名として使用されます。

名前空間の宣言

図 1. 名前空間を利用する XML フラグメント

名前空間宣言は、通常、名前空間 URI を特定のプレフィックスにマップするために使用されます。 プレフィックスと名前空間のマッピングのスコープは、名前空間宣言が行われる要素とそのすべての子のスコープです。 プレフィックス xmlns: で始まる属性宣言は名前空間宣言です。 このような属性宣言の値は、名前空間 名である名前空間 URI である必要があります。

ルート要素に名前空間名にプレフィックスをマップする名前空間宣言が含まれている XML ドキュメントの例を次に示します。その子要素には、プレフィックスbkinvを名前空間名 urn:xmlns:25hoursaday-com:bookstore にマップする名前空間宣言を含む要素がurn:xmlns:25hoursaday-com:inventory-tracking含まれていますinventory

<bk:bookstore xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">
 <bk:book> 
    <bk:title>Lord of the Rings</bk:title> 
    <bk:author>J.R.R. Tolkien</bk:author>
    <inv:inventory status="in-stock" isbn="0345340426" 
        xmlns:inv="urn:xmlns:25hoursaday-com:inventory-tracking" />
 </bk:book> 
</bk:bookstore>

上記の例では、名前空間名の名前空間宣言 urn:xmlns:25hoursaday-com:bookstore のスコープは要素全体 bk:bookstore ですが、 の urn:xmlns:25hoursaday-com:inventory-tracking スコープは 要素です inv:inventory 。 名前空間対応プロセッサは、両方の名前空間の項目を相互に独立して処理できるため、XML ドキュメントの多層処理を実行できます。 たとえば、 RDDL ドキュメント は、Web ブラウザーでレンダリングできる有効な XHTML ドキュメントですが、XML 名前空間のメンバーに関するコンピューターで読み取り可能なリソースを検索するために使用できる名前空間の要素 http://www.rddl.org を使用する情報も含まれています。

定義上、プレフィックス xmlXML 名前空間名 にバインドされ、この特殊な名前空間は、整形式のすべての XML ドキュメントのドキュメント スコープで自動的に事前宣言されます。

既定の名前空間

名前空間宣言に関する前のセクションでは、既定の名前空間が除外されているため、完全には完了していません。 既定の名前空間宣言は、名前 xmlns を持つ属性宣言であり、その値は名前空間名である名前空間 URI です。

既定の名前空間宣言では、そのスコープ内のすべての固定されていない要素名が宣言されている名前空間から指定されます。 プレフィックスと名前空間のマッピングの代わりに既定の名前空間を使用する bookstore の例を次に示します。

<bookstore xmlns="urn:xmlns:25hoursaday-com:bookstore">
 <book> 
    <title>Lord of the Rings</title> 
    <author>J.R.R. Tolkien</author>
    <inv:inventory status="in-stock" isbn="0345340426" 
        xmlns:inv="urn:xmlns:25hoursaday-com:inventory-tracking" />
 </book> 
</bookstore>

要素を除く上記の例のすべての要素は inv:inventory 、 名前空間に urn:xmlns:25hoursaday-com:bookstore 属しています。 既定の名前空間の主な目的は、名前空間を使用する XML ドキュメントの詳細度を減らすことです。 ただし、要素名に明示的にマップされたプレフィックスを使用する代わりに既定の名前空間を使用すると、ドキュメント内の要素が名前空間スコープであることが明らかではないので、混乱を招く可能性があります。

また、通常の名前空間宣言とは異なり、 xmlns 属性の値を空の文字列に設定することで、既定の名前空間宣言を宣言解除できます。 既定の名前空間宣言の宣言を解除することは、ドキュメントの一部では名前空間に属しているが、別の部分には含まれない、未修正の名前を持つドキュメントにつながる可能性があるため、避ける必要がある方法です。 たとえば、下のドキュメントでは、 bookstore 要素のみが から urn:xmlns:25hoursaday-com:bookstore であり、他の未固定要素には名前空間名がありません。

<bookstore xmlns="urn:xmlns:25hoursaday-com:bookstore">
 <book > 
    <title>Lord of the Rings</title> 
    <author>J.R.R. Tolkien</author>
    <inv:inventory status="in-stock" isbn="0345340426" 
        xmlns:inv="urn:xmlns:25hoursaday-com:inventory-tracking" />
 </book> 
</bookstore>

この方法は、XML ドキュメントの閲覧者にとって非常に混乱を招くため、避ける必要があります。 名前空間宣言の宣言解除の詳細については、「 Namespaces Future」のセクションを参照してください。

修飾名と展開名

修飾名 (QName とも呼ばれます) は、ローカル名と呼ばれる XML 名で、必要に応じてプレフィックスとコロン (':') 文字と呼ばれる別の XML 名の前に付けられます。 プレフィックスとして使用される XML 名とローカル名は NCName 運用と一致する必要があります。つまり、コロン文字を含めてはいけません。 修飾名のプレフィックスは、名前空間 URI にプレフィックスをマッピングするスコープ内の名前空間宣言を使用して名前空間 URI にマップされている必要があります。 修飾名は、属性または要素名として使用できます。

QNames は、ドキュメント内の要素と属性が派生する名前空間を決定するための重要なニーモニック ガイドですが、XML 対応プロセッサにとって重要になることはほとんどありません。 たとえば、次の 3 つの XML ドキュメントは、XML スキーマ検証コントロールなど、さまざまな XML テクノロジによって同じように扱われます。

<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
        <xs:complexType id="123" name="fooType"/>
</xs:schema>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <xsd:complexType id="123" name="fooType"/>
</xsd:schema>

<schema xmlns="http://www.w3.org/2001/XMLSchema">
        <complexType id="123" name="fooType"/>
</schema>

W3C XML パス言語の推奨事項では、展開された名前が名前空間名とローカル名で構成されるペアとして記述されています。 普遍的な名前は、同じ概念を記述するためにジェームズ・クラークによって造られた代替用語です。 汎用名は、中かっこで囲んだ名前空間名とローカル名で構成されます。 名前空間は、ユニバーサル名のレンズを通して見ると、人々に意味を持つ傾向があります。 前の例の 3 つの XML ドキュメントを、QNames を汎用名に置き換えて示します。 以下の構文は有効な XML 構文ではないことに注意してください。

<{http://www.w3.org/2001/XMLSchema}schema>  
<{http://www.w3.org/2001/XMLSchema}complexType id="123" name="fooType"/>
</{http://www.w3.org/2001/XMLSchema}schema>

<{http://www.w3.org/2001/XMLSchema}schema>  
<{http://www.w3.org/2001/XMLSchema}complexType id="123" name="fooType"/>
</{http://www.w3.org/2001/XMLSchema}schema>

<{http://www.w3.org/2001/XMLSchema}schema>  
<{http://www.w3.org/2001/XMLSchema}complexType id="123" name="fooType"/>
</{http://www.w3.org/2001/XMLSchema}schema>

多くの XML アプリケーションでは、XML ドキュメント内の要素と属性の汎用名が重要であり、特定の QName で使用されるプレフィックスの値ではありません。 XML の名前空間に関する推奨事項が名前空間の指定に拡張された名前アプローチを採用しない主な理由は、その詳細さによるものです。 代わりに、プレフィックス マッピングと既定の名前空間が提供され、名前空間 URI を無限に入力して手根トンネル症候群を開発するのを防ぐことができます。

名前空間と属性

名前空間宣言は、属性の名前にプレフィックスが付かない限り、属性には適用されません。 以下に示す XML ドキュメントでは、 title 属性は 要素に bk:book 属し、名前空間を持たないのに対し、 bk:title 属性は名前空間名としてを持 urn:xmlns:25hoursaday-com:bookstore っています。 両方の属性が同じローカル名を持っていても、ドキュメントは整形式であることに注意してください。

<bk:bookstore xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">
   <bk:book title="Lord of the Rings, Book 3" bk:title="Return of the King"/> 
</bk:bookstore> 

次の例では、 title 属性には名前空間がなく、既定の book 名前空間が指定されていても 要素に属しています。 つまり、属性は既定の名前空間を継承できません。

<bookstore xmlns="urn:xmlns:25hoursaday-com:bookstore">
   <book title="Lord of the Rings, Book 3" /> 
</bookstore> 

名前空間 URI

名前空間名は、RFC 2396 で指定されている UNIFORM Resource Identifier (URI) です。 URI は、Uniform Resource Locators (URL) または Uniform Resource Names (URN) のいずれかです。 URL はインターネット上のリソースの場所を指定するために使用されますが、URL は情報リソースの永続的で場所に依存しない識別子であると想定されています。 名前空間名は、文字に対して同じ文字である場合にのみ同一と見なされます (大文字と小文字は区別されます)。 URI を名前空間名として使用する主な理由は、グローバルに一意の ID を指定するためのメカニズムが既に用意されていることです。

XML 名前空間の推奨事項では、名前空間名は一意の識別子としてのみ機能し、ネットワーク取得可能なリソースを実際に識別する必要はないことを示しています。 これは、特に名前空間名としての HTTP ベースの URL の使用が人気を高めているため、XML ドキュメントの作成者とユーザーの間で大きな混乱を招きました。 多くのアプリケーションはこのような URI をハイパーリンクに変換するため、多くのユーザーに対して、これらの "リンク" が Web ページやその他のネットワーク取得可能なリソースにつながらないという刺激を受けます。 私は、ソーシャルな状況で偽の電話番号を与えられたのになだめた一人のユーザーを覚えています。

ユーザーを混乱させない解決策の 1 つは、リソースのネットワーク取得可能性を意味しない名前空間の名前付けスキーマを使用することです。 私は個人的にこの目的のためにスキームを urn:xmlns: 使用し、個人的な使用のためにXMLドキュメントを作成する場合と同様の urn:xmlns:25hoursaday-com 名前空間名を作成します。 ホームグラウン名前空間 URI の問題は、グローバルに一意でならずに、XML 内の名前の推奨事項の意図に反して実行される可能性があるということです。 名前空間 URI の一部として個人用ドメイン名 http://www.25hoursaday.com を使用して、グローバルに一意の要件を回避します。

もう 1 つの解決策は、ネットワーク取得可能なリソースを名前空間名である URI に残すことです。たとえば、 は XSLT 名前空間と RDDL 名前空間で行われます。 通常、このような URI は実際には HTTP URL です。 このような URL に名前を付ける良い方法は、W3C で優先される形式を使用することです。これは次のとおりです。

      http://my.domain.example.org/product/[year/month][/area]

バージョン管理メカニズムとして同様に構造化された名前空間名を使用する方法の詳細については、「 名前空間とバージョン 管理」のセクションを参照してください。

DOM、XPath、および名前空間に関する XML 情報セット

W3C では、XML ドキュメントのデータ モデルを提供する多くのテクノロジが定義されています。 これらのデータ モデルは一般に一致していますが、歴史的な理由により、さまざまなエッジ ケースの処理方法が異なる場合があります。 XML 名前空間と名前空間宣言の処理は、W3C の推奨事項として存在する 3 つの主要なデータ モデルで異なる方法で扱われるエッジ ケースの例です。 3 つのデータ モデルは、XPath データ モデル、ドキュメント オブジェクト モデル (DOM)、および XML 情報セットです。

XML 情報セット (XML インフォセット) は、XML ドキュメント内のデータの抽象的な説明であり、XML ドキュメントの主要なデータ モデルと見なすことができます。 XPath データ モデルは、XML ドキュメントのクエリを実行するときに走査されるツリーベースのモデルであり、XML 情報セットに似ています。 DOM は両方のデータ モデルの前にありますが、さまざまな方法で両方のデータ モデルに似ています。 DOM と XPath の両方のデータ モデルは、XML インフォセットの解釈と見なすことができます。

ドキュメント オブジェクト モデル (DOM) の名前空間

DOM レベル 3 仕様の XML 名前空間セクションでは、名前空間宣言は、名前空間名として、プレフィックスまたは修飾名xmlnsとして持つhttp://www.w3.org/2000/xmlns/通常の属性ノードと見なされます。

DOM 内の要素と属性には、ドキュメント内の場所が変更されるかどうかにかかわらず、作成後に変更できない名前空間名があります。

XPath データ モデルの名前空間

W3C XPath の推奨事項では、名前空間宣言は 属性ノード とは見なされず、その容量内でそれらにアクセスすることはできません。 代わりに、XPath では、XML ドキュメント内のすべての要素に、XPath 名前空間 ナビゲーション軸を使用して取得できる名前空間ノードが多数存在します。

ドキュメント内の各要素には、その特定の要素のスコープ内の名前空間宣言ごとに一意の名前空間ノードのセットがあります。 名前空間ノードは、その名前空間の各要素に固有です。 したがって、同じ名前空間宣言を表す 2 つの異なる要素の名前空間ノードは同一 ではありません

XML 情報セット内の名前空間

XML インフォセットの推奨事項では、名前空間宣言は 属性情報項目と見なされます。

さらに、XPath データ モデルと同様に、XML ドキュメントの情報セット内の各 要素情報項目 には、要素のスコープ内にある各名前空間の名前空間 情報 項目があります。

XPath、XSLT、名前空間

XPath とも呼ばれる W3C XML パス言語は、XML ドキュメントの一部に対応するために使用され、XSLT、XPointer、XML スキーマ、DOM レベル 3 など、多くの W3C XML テクノロジで使用されます。 XPath では、ファイル システムや URL で使用されるのと同様の階層型アドレス指定メカニズムを使用して、XML ドキュメントの一部を取得します。 XPath では、文字列、数値、ブール値の基本的な操作がサポートされています。

XPath と名前空間

XPath データ モデルは、XML ドキュメントを要素、属性、テキスト ノードなどのノードのツリーとして扱います。各ノードの名前は、ローカル名とその名前空間名 (つまり、ユニバーサル名または展開名) の組み合わせです。

名前空間のない要素ノードと属性ノードの場合、XPath クエリの実行はかなり簡単です。 コマンド ラインを使用して XML ドキュメントのクエリを実行するために使用できる次のプログラムを使用して、XPath クエリに対する名前空間の影響を示します。

using System.Xml.XPath; 
using System.Xml; 
using System;
using System.IO; 

class XPathQuery{

public static string PrintError(Exception e, string errStr){

  if(e == null) 
    return errStr; 
  else
    return PrintError(e.InnerException, errStr + e.Message ); 
} 

 public static void Main(string[] args){

   if((args.Length == 0) || (args.Length % 2)!= 0){
     Console.WriteLine("Usage: xpathquery source query <zero or more 
prefix and namespace pairs>");
      return; 
   }
   
   try{
     
     //Load the file.
     XmlDocument doc = new XmlDocument(); 
     doc.Load(args[0]); 

     //create prefix<->namespace mappings (if any) 
     XmlNamespaceManager  nsMgr = new XmlNamespaceManager(doc.NameTable);

     for(int i=2; i < args.Length; i+= 2)
       nsMgr.AddNamespace(args[i], args[i + 1]); 

     //Query the document 
     XmlNodeList nodes = doc.SelectNodes(args[1], nsMgr); 

     //print output 
     foreach(XmlNode node in nodes)
       Console.WriteLine(node.OuterXml + "\n\n");

   }catch(XmlException xmle){
     Console.WriteLine("ERROR: XML Parse error occured because " + 
PrintError(xmle, null));
   }catch(FileNotFoundException fnfe){
     Console.WriteLine("ERROR: " + PrintError(fnfe, null));
   }catch(XPathException xpath){
     Console.WriteLine("ERROR: The following error occured while querying 
the document: " 
             + PrintError(xpath, null));
   }catch(Exception e){
     Console.WriteLine("UNEXPECTED ERROR" + PrintError(e, null));
   }
 }
}

名前空間を宣言しない次の XML ドキュメントを考えると、コードの後の例に示すように、クエリはかなり簡単です。

<?xml version="1.0" encoding="utf-8" ?> 
<bookstore> 
  <book genre="autobiography">
    <title>The Autobiography of Benjamin Franklin</title>
    <author>
      <first-name>Benjamin</first-name>
      <last-name>Franklin</last-name>
    </author>
    <price>8.99</price>
  </book>
  <book genre="novel">
    <title>The Confidence Man</title>
    <author>
      <first-name>Herman</first-name>
      <last-name>Melville</last-name>
    </author>
    <price>11.99</price>
  </book>
</bookstore>

例 1

  1. xpathquery.exe bookstore.xml /bookstore/book/title

    親が 要素である要素の book 子であるすべてのタイトル要素を bookstore 選択します。これは、次を返します。

       <title>The Autobiography of Benjamin Franklin</title>
       <title>The Confidence Man</title>
    
  2. xpathquery.exe bookstore.xml //@genre

    ドキュメント内のすべての genre 属性を選択し、次を返します。

       genre="autobiography"
       genre="novel"
    
  3. xpathquery.exe bookstore.xml //title[(../author/first-name = 'Herman')]

    作成者の名が "ハーマン" であるすべてのタイトルを選択し、次を返します。

       <title>The Confidence Man</title>  
    

    ただし、名前空間がミックスに追加されると、物事は単純ではなくなります。 以下のファイルは、名前空間と 1 つの属性を要素のいずれかに追加する場合を除き、元の book ファイルと同じです。

    <bookstore xmlns="urn:xmlns:25hoursaday-com:bookstore">
      <book genre="autobiography">
        <title>The Autobiography of Benjamin Franklin</title>
        <author>
          <first-name>Benjamin</first-name>
          <last-name>Franklin</last-name>
        </author>
        <price>8.99</price>
      </book>
      <bk:book genre="novel" bk:genre="fiction" 
    xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">
        <bk:title>The Confidence Man</bk:title>
        <bk:author>
          <bk:first-name>Herman</bk:first-name>
          <bk:last-name>Melville</bk:last-name>
        </bk:author>
        <bk:price>11.99</bk:price>
      </bk:book>
    </bookstore>
    

    既定の名前空間は XML ドキュメント全体のスコープ内にあり、プレフィックス bk を名前空間名 urn:xmlns:25hoursaday-com:bookstore にマップする名前空間宣言は、2 番目の book 要素のスコープ内のみであることに注意してください。

例 2

  1. xpathquery.exe bookstore.xml /bookstore/book/title

    親が 要素である要素の book 子であるすべてのタイトル要素を bookstore 選択します。この要素は NO RESULTS を返します。

  2. xpathquery.exe bookstore.xml //@genre

    ドキュメント内のすべての属性を genre 選択し、次の値を返します。

       genre="autobiography"
       genre="novel"
    
  3. xpathquery.exe bookstore.xml //title[(../author/first-name = 'Herman')]

    作成者の名が "ハーマン" であるすべてのタイトルを選択します。このタイトルは NO RESULTS を返します。

    XPath クエリの前置されていない名前は、名前空間のない要素または属性に適用されるため、最初のクエリは結果を返しません。 ターゲット ドキュメントには、名前空間をbookstorebook持たない要素、、または title 要素がありません。 2 番目のクエリは、名前空間を持たないすべての属性ノードを返します。 名前空間宣言は、クエリによって返される両方の属性ノードのスコープ内にありますが、名前空間宣言は前置されていない名前の属性には適用されないため、名前空間はありません。 3 番目のクエリは、最初のクエリが結果を返さないのと同じ理由で結果を返しません。

    名前空間に対応する XPath クエリを実行する方法は、XPath エンジンへの名前空間マッピングにプレフィックスを指定し、そのプレフィックスをクエリで使用することです。 指定されたプレフィックスは、ターゲット ドキュメント内のプレフィックス マッピングの名前空間と同じである必要はありません。また、空でないプレフィックスである必要があります。

例 3

  1. xpathquery.exe bookstore.xml /b:bookstore/b:book/b:title b urn:xmlns:25hoursaday-com:bookstore

    bookstoreが 要素であり、次を返す要素のbook子であるすべてのタイトル要素を選択します。

        <title xmlns="urn:xmlns:25hoursaday-com:bookstore">The Autobiography of Benjamin Franklin</title>
       <bk:title xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">The Confidence Man</bk:title>
    
    
  2. xpathquery.exe bookstore.xml //@b:genre b urn:xmlns:25hoursaday-com:bookstore

    Sは、次を返すドキュメントの "urn:xmlns:25hoursaday-com:bookstore" 名前空間からすべての genre 属性を選択します。

       bk:genre="fiction"
    
    
  3. xpathquery.exe bookstore.xml //bk:title[(../bk:author/bk:first-name = 'Herman')] bk urn:xmlns:25hoursaday-com:bookstore

    作成者の名が "ハーマン" であるすべてのタイトルを選択し、次を返します。

       <bk:title xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">The Confidence Man</bk:title>
    
    

    メモ この最後の例は前の例と同じですが、名前空間に対応するように書き換えられます。

XPath の使用方法の詳細については、Aaron Skonnard の記事「 Addressing Infosets with XPath 」を参照し、 ZVON.org XPath チュートリアルの例を参照してください。

XSLT と名前空間

W3C XSL 変換 (XSLT) の推奨事項では、XML ドキュメントを他の XML ドキュメントに変換するための XML ベースの言語について説明します。 XSLT 変換 (XML スタイル シートとも呼ばれます) では、パターン (XPath) を使用してターゲット ドキュメントの側面を照合します。 ターゲット ドキュメント内のノードを照合すると、成功した一致の出力を指定するテンプレートをインスタンス化し、ドキュメントの変換に使用できます。

名前空間のサポートは XSLT に緊密に統合されています。XPath はソース ドキュメント内のノードの照合に使用されるためです。 XSLT 内で XPath 式で名前空間を使用する方が、DOM を使用するよりもはるかに簡単です。

次の例には、次のものが含まれています。

  • コマンド ラインからの変換の実行に使用するプログラム。
  • 名前空間からドキュメントにtitle対して実行するときに、ソース XML ドキュメント内の名前空間からurn:xmlns:25hoursaday-com:bookstoreすべての要素を出力する bookstore XSLT urn:xmlns:25hoursaday-com:bookstore スタイルシート。
  • 結果の出力。

プログラム

Imports System.Xml.Xsl
Imports System.Xml
Imports System
Imports System.IO

Class Transformer

   Public Shared Function PrintError(e As Exception, errStr As String) As String
      
      If e Is Nothing Then
         Return errStr
      Else
         Return PrintError(e.InnerException, errStr + e.Message)
      End If 
   End Function 'PrintError
   
   'Entry point which delegates to C-style main Private Function
   Public Overloads Shared Sub Main()
      Run(System.Environment.GetCommandLineArgs())
   End Sub 'Main 
   
   
   Overloads Public Shared Sub Run(args() As String)
      
      If args.Length <> 2 Then
         Console.WriteLine("Usage: xslt source stylesheet")
         Return
      End If
      
      Try
         
         'Create the XslTransform object.
         Dim xslt As New XslTransform()
         
         'Load the stylesheet.
         xslt.Load(args(1))
         
         'Transform the file.
         Dim doc As New XmlDocument()
         doc.Load(args(0))
         
         xslt.Transform(doc, Nothing, Console.Out)
      
      Catch xmle As XmlException
         Console.WriteLine(("ERROR: XML Parse error occured because " + 
PrintError(xmle, Nothing)))
      Catch fnfe As FileNotFoundException
         Console.WriteLine(("ERROR: " + PrintError(fnfe, Nothing)))
      Catch xslte As XsltException
         Console.WriteLine(("ERROR: The following error occured while 
transforming the document: " + PrintError(xslte, Nothing)))
      Catch e As Exception
         Console.WriteLine(("UNEXPECTED ERROR" + PrintError(e, Nothing)))
      End Try
   End Sub
End Class 'Transformer

XSLT スタイルシート

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
   xmlns:b="urn:xmlns:25hoursaday-com:bookstore">

<xsl:template match="b:bookstore">
<book-titles>
<xsl:apply-templates select="b:book/b:title"/>
</book-titles>
</xsl:template>

<xsl:template match="b:title"> 
<xsl:copy-of select="." />
</xsl:template>
</xsl:stylesheet>

出力

<?xml version="1.0" ?>
<book-titles xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
xmlns:ext="urn:my_extensions" xmlns:b="urn:xmlns:25hoursaday-com:bookstore">
<title xmlns="urn:xmlns:25hoursaday-com:bookstore">The Autobiography of 
Benjamin Franklin</title>
<bk:title xmlns="urn:xmlns:25hoursaday-com:bookstore" 
xmlns:bk="urn:xmlns:25hoursaday-com:bookstore">The Confidence 
Man</bk:title>
</book-titles>

スタイルシートからの名前空間宣言は、出力 XML ドキュメントのルート ノードで終了します。 また、XSLT 名前空間が出力 XML ドキュメントに含まれていないことにも注意してください。

XSLT 変換の出力から XSLT スタイルシートを生成するのは、プロセッサが実際のスタイルシート ディレクティブから出力要素を決定できる必要があるため、少し面倒です。 この問題に対処するには、2 つの方法があります。どちらも、次の XMLT スタイルシートを出力として生成するスタイルシートを示して説明します。

<xslt:stylesheet version="1.0" 
 xmlns:xslt="http://www.w3.org/1999/XSL/Transform">
<xslt:output method="text"/>
<xslt:template match="/"><xslt:text>HELLO WORLD</xslt:text></xslt:template>
</xslt:stylesheet>

最初のメソッドでは、作成するスタイルシートを含む変数を作成し、 属性とdisable-output-escaping組み合わせて を使用してvalue-ofスタイルシートを作成します。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml"  encoding="utf-8"/> 
  <xsl:variable name="stylesheet">
 &lt;xslt:stylesheet version="1.0" 
 xmlns:xslt="http://www.w3.org/1999/XSL/Transform"&gt;
&lt;xslt:output method="text"/&gt;
&lt;xslt:template match="/"&gt;&lt;xslt:text&gt;HELLO 
WORLD&lt;/xslt:text&gt;&lt;/xslt:template&gt;
&lt;/xslt:stylesheet&gt;
 </xsl:variable> 
 <xsl:template match="/">
  <xsl:value-of select="$stylesheet" disable-output-escaping="yes" /> 

  </xsl:template>
  </xsl:stylesheet>

この最初の方法は、作成するスタイルシートを変数に配置できるように簡単にパーティション分割できる場合に最適です。 この手法は迅速かつ簡単ですが、 粗いハック のカテゴリにも分類されます。これは、通常、柔軟性を必要とする状況に直面すると管理不能になる傾向があります。 たとえば、新しいスタイルシートの作成にテキストの動的な作成が多く含まれ、スタイルシートディレクティブと絡み合う場合、前述の 粗大ハックには次の方法が適しています。

<xslt:stylesheet version="1.0" xmlns:xslt="http://www.w3.org/1999/XSL/Transform"
 xmlns:alias="http://www.w3.org/1999/XSL/Transform-alias">
  <xslt:output method="xml"  encoding="utf-8"/> 

 <xslt:namespace-alias stylesheet-prefix="alias" result-prefix="xslt"/> 

 <xslt:template match="/">
 <alias:stylesheet version="1.0">
<alias:output method="text"/>
<alias:template match="/"><alias:text>HELLO 
WORLD</alias:text></alias:template>
</alias:stylesheet>
  </xslt:template>

  </xslt:stylesheet>

上記のドキュメントでは、 ディレクティブを namespace-alias 使用して、バインド先の alias プレフィックスと名前空間名を、バインド先の xslt プレフィックスと名前空間名に置き換えます。

名前空間は、XSLT の拡張機能のメカニズムを指定するためにも使用されます。 名前空間プレフィックス付き関数は、XSLT 関数と同じ方法で実行される関数を作成できます。 同様に、特定の名前空間の要素は XSLT の拡張機能として扱われ、などの変換ディレクティブであるtemplatecopyvalue-ofかのように実行できます。 名前空間ベースの拡張関数を使用して署名応答を出力するHello World プログラムの例を次に示します。

<stylesheet version="1.0" 
 xmlns="http://www.w3.org/1999/XSL/Transform"
 xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
 xmlns:newfunc="urn:my-newfunc">
 <output method="text"/>

<template match="/">
 <value-of select="newfunc:SayHello()" />
</template>

 <msxsl:script language="JavaScript" implements-prefix="newfunc">
        function SayHello() {
           return "Hello World";
        }
 </msxsl:script>
</stylesheet>

XML 名前空間に関する注意事項

XML の名前空間は、他の便利なツールと同様に不適切に使用でき、ユーザーが認識できない場合に問題を引き起こす可能性のあるさまざまな微妙な点があります。 このセクションでは、XML 名前空間のユーザーが通常問題を抱えたり、誤解を受けたりする領域について説明します。

バージョン管理と名前空間

XML インスタンス ドキュメントの異なるバージョンを作成するために、実際には 2 つの主要なメカニズムが使用されます。 1 つの方法は、XSLT で行われるようにルート要素で version 属性を使用することです。もう 1 つのメソッドは、要素の名前空間名をバージョン管理メカニズムとして使用することです。 現在、名前空間に基づくバージョン管理は非常に一般的です。特に W3C では、SOAP、XHTML、XML スキーマ、RDF などのさまざまな XML テクノロジにこのメカニズムを使用しています。 名前空間を使用してバージョン管理されるドキュメントの名前空間 URI は、通常、次の形式です。

      http://my.domain.example.org/product/[year/month][/area]

以降のバージョンで名前空間名を変更して XML ドキュメントのバージョン管理を行う際の主な問題は、ドキュメントを処理する XML 名前空間対応アプリケーションがドキュメントで動作しなくなり、アップグレードする必要があることを意味することです。 これは主に、バージョンの変更頻度が低いドキュメント形式で役立ちますが、変更すると要素と属性のセマンティクスが変更されるため、すべてのプロセッサが新しいバージョンで動作しなくなり、誤って解釈される可能性があります。

一方、ルート要素の version 属性に基づく XML ドキュメントのバージョン管理メカニズムで十分なシナリオがいくつかあります。 version 属性は、ドキュメントの構造の変更に下位互換性がある場合に主に役立ちます。 次の状況は、 バージョン 属性の使用が賢明な選択であるすべての領域です。

  • 要素と属性のセマンティクスは変更されません。
  • ドキュメントに対する変更には、要素と属性の追加が含まれますが、削除されることはほとんどありません。
  • さまざまなバージョンの処理ソフトウェアとのアプリケーション間の相互運用性が必要です。

どちらのバージョン管理手法も相互に排他的ではなく、同時に使用できます。 たとえば、XSLT では、 ルート要素の version 属性と、 バージョン管理された名前空間 URI の両方が使用されます。 バージョン属性は、XML ドキュメントの形式に対する下位互換性のある増分変更に使用され、名前空間名の変更はドキュメントのセマンティクスを大幅に変更するために行われます。

ドキュメントの種類

さまざまな XML 関連のメーリング リストに関するいくつかの哲学的な議論で説明されているように、 ドキュメントの種類 という用語は誤解を招くものです。 多くの場合、ルート要素の名前空間名を使用してドキュメントを処理する方法を決定できますが、これは一般的なルールとは言え、開発者が XML 語彙を組み合わせることができるように正確に設計されているため、XML 名前空間の精神に違反します。

ルート要素の名前空間 URI がドキュメント型の概念と同等であると考える理由の本質をキャプチャする簡潔な投稿は、 XML-DEV 上の Rick Jelliffe によるこの投稿です。 投稿の本質は、XML ドキュメントに含めることができるさまざまな種類があることです。これには、ドキュメントの 種類 (DTD)、 MIME メディアの種類xsi:schemaLocation 属性で指定されたスキーマ定義、ファイル拡張子、ルート要素の名前空間名などです。 したがって、多くの場合、ドキュメントを調べるときにどのような観点を取ると決めたかによって、ドキュメントの種類が異なる可能性が高くなります。

ルート要素の名前空間 URI を見るだけで実際のドキュメントの種類が誤って区別される可能性がある XML ドキュメントの 2 つの例は、 RDDL ドキュメント (サンプルでは、そのルート要素が XHTML 名前空間からのものであることに注意してください) と、ルート要素が W3C XML スキーマ名前空間からの 注釈付きマッピング スキーマです。

簡単に言うと、ドキュメントの型は、そのルート要素の名前空間 URI を調べることによって確定できません。 それ以外の考えは愚かです。

名前空間の将来

XML の世界には、XML 名前空間に関して開発されたいくつかの問題に取り組むことに重点を置いた開発がいくつかあります。 まず、W3C XML 名前空間の推奨事項の現在のドラフトでは、プレフィックスにマップされている宣言解除名前空間のメカニズムは提供されません。 W3C XML 名前空間 v1.1 作業ドラフト は、インスタンス ドキュメントでプレフィックス名前空間マッピングを宣言解除するためのメカニズムを提供することで、この監視を修正することを目的としています。

名前空間 URI の内容を逆参照しようとする際に何を返すべきかについての議論は、XML 世界で議論を引き起こしており、現在 、W3C の技術アーキテクチャ グループによる審議の焦点となっています。 現在のバージョンの XML 名前空間の推奨事項では、名前空間 URI が実際に解決可能である必要はありません。これは、名前空間 URI は、インターネット上のリソースの場所ではなく、一意の識別子として使用される名前空間名にすぎないためです。

Tim Bray ( XML 言語XML 名前空間 に関する推奨事項の両方の元のエディターの 1 つ) は、名前空間 URI と名前空間ドキュメントに関する問題に関する 徹底的な取り扱 いを記述しています。これらのドキュメントから取得できる場合と取得できない場合があります。 このドキュメントには、名前空間ドキュメントの作成に使用するように設計された Resource Directory Description Language (RDDL) の作成の背後にある理由の多くが含まれています。

Dare Obasanjo は Microsoft の WebData チームのメンバーであり、特に、.NET Framework、Microsoft XML Core Services (MSXML)、Microsoft Data Access Components (MDAC) の System.Xml 名前空間と System.Data 名前空間内のコンポーネントを開発しています。

この記事に関する質問やコメントは、GotDotNet の Extreme XML メッセージ ボード に自由に投稿できます。