XSLT 2.0で便利になった機能(37) 数値型、演算子

XSLTといってもいわゆる「文書型」のXMLを変換するのと、「データ型」のXMLを変換するのとでは事情が変わります.私はもっぱら「文書型」のXMLの方しかやっていないので、数値型の詳細や演算子に触れる機会がなかったのですが、見る機会がありましたので紹介します.
 
まずXPath2.0では、扱える数値型の型が大きく変わりました.XPath1.0では数値といえばnumber型(実体はdouble型)しかなかったのですが、XPath2.0ではXML Schemaで定義された以下の数値型が使えます.
 
xs:decimal
xs:float
xs:double
xs:integer
 
XML Schemaではこれ以外にも、xs:integerの継承型としてxs:short、xs:byteなどがありますが、これらはSchema AwareなXSLTプロセッサでないと使うことができません.(オープンソースバージョンのSaxonでは使うことができません.saxonicaでエンタープライズ版を買う必要があります.)
 
AltovaXML.exeはSchema Awareですので次のようなxs:integerから派生した型をつかうことができます.
 
xs:byte
xs:int
xs:long
xs:negativeInteger
xs:nonNegativeInteger
xs:nonPositiveInteger
xs:positiveInteger
xs:short
xs:unsignedByte
xs:unsignedInt
xs:unsignedLong
xs:unsignedShort
 
例えばこんな具合です.
 
<xsl:variable name="us" select="xs:unsignedShort(5)" as="xs:unsignedShort"/>
<xsl:variable name="us2" select="xs:unsignedShort(7)" as="xs:unsignedShort"/>
<xsl:variable name="resultUsDiv" select="$us div $us2" as="xs:anyAtomicType"/>
<xsl:message select="'$resultUsDiv instance of xs:decimal=',$resultUsDiv instance of xs:decimal, 'result=', $resultUsDiv"/>
 
これは次のように出力されます.
 
XSL message: $resultUsDiv instance of xs:decimal= true result= 0.7142857142857142857142857142
 
でもコードを見てわかるとおり、わざわざこのような型を意識的に使うことはないでしょう.(やっかいで仕方がありません)やはり、XML Scemaで入力するXMLの要素や属性のデータ型が定義されている場合に使うのが自然です.
 
せっかくSchema AwareなAltovaXML.exeを使ったので、ちょっと脱線して、XML Schemaで型付けされた入力XMLデータをどのようにスタイルシートでその型にマッピングするのか試してみました.
 
[入力XMLファイル]
<?xml version="1.0" encoding="UTF-8" ?>
<data xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="input_schema.xml">
    <product name="鉛筆">
        <price maker="A" value="100"/>
        <price maker="B" value="110"/>
        <price maker="C" value="150"/>
    </product>
</data>
 
[XML Schema (input_schema.xml)]
<?xml version="1.0" encoding="UTF-8" ?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
    <xs:element name="data" type="dataType"/>
    <xs:complexType name="dataType">
        <xs:sequence>
            <xs:element ref="product" maxOccurs="unbounded"/>
        </xs:sequence>
    </xs:complexType>
    <xs:element name="product" type="productType"/>
    <xs:complexType name="productType">
        <xs:sequence>
            <xs:element ref="price" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string"/>
    </xs:complexType>
    <xs:element name="price" type="priceType"/>
    <xs:complexType name="priceType">
        <xs:attribute name="maker" type="xs:string"/>
        <xs:attribute name="value" type="xs:short"/>
    </xs:complexType>
</xs:schema>
 
このような例のときスタイルシートではvalue属性をどのようにxs:shortと判断できるのでしょうか?以下のコードでは
 
<xsl:variable name="valueIsShort" select="data(/data[1]/product[1]/price[1]/@value) instance of xs:short" as="xs:boolean"/>
<xsl:message select="'$valueIsShort=',$valueIsShort,"/>
 
結果は
 
XSL message: $valueIsShort= true
 
でした.data関数がノードの@valueXML Schemaで型付けされたxs:shortにマッピングしてくれます.
 
さて数値型でxs:integerが使えるようになったので、演算子も追加されています.従来除算はdivだけでしたが整数除算のidivが加わりました.
 
 <xsl:message select="'7 idiv 3 =',7 idiv 3"/>
 
は、
 
7 idiv 3 = 2
 
と出力されます.
 
*Altova XMLは以下からダウンロードできます.無料で使えるSchema Awareなプロセッサは貴重なので一度お試しください.私の使っているのはAltova XML® 2010ですが、AltovaXML® 2011 になっているようです.(Saxonに比べてAltovaはエラーメッセージがそっけないですが...)