属性と真偽判定

はじめに

属性の有無や属性値によって真偽の判定が変る.いくつか例を考えて整理してみよう.

実行環境は以下の通り.

  • Microsoft Windows XP SP2+セキュリティパッチたくさん
  • Cygwin 1.5.24(uname -r で確認)
  • Saxon-B 9.0.0.2J(インストールしたディレクトリを以下${saxon_home}と表記)

属性がある/ない

3の倍数と3がつく数字のときにアホになるxml(aho01.xml)があるとしよう.アホになる数字には属性ahoがつく.

aho01.xml:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <number>1</number>
    <number>2</number>
    <number aho="true">3</number> <!-- アホになる数字には属性ahoが付く -->
    <number>4</number>
    <number>5</number>
    <number aho="true">6</number>
    <number>7</number>
    <number>8</number>
    <number aho="true">9</number>
    <number>10</number>
    <number>11</number>
    <number aho="true">12</number>
    <number aho="true">13</number>
    <number>14</number>
    <number aho="true">15</number>
</root>

このxmlに以下のxslt(aho01.xsl)を適応すると,アホになる数字(number_become_aho)とアホにならない数字(number_not_aho)を分けて出力できる.

aho01.xsl:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output
    method="xml"
    encoding="UTF-8"
    indent="yes"/>

  <xsl:template match="/root">
    <root>
      <number_become_aho>
        <xsl:apply-templates select="number[@aho]"/> <!-- 属性ahoが存在する -->
        <!-- <xsl:apply-templates select="number[boolean(@aho)]"/> boolean()はあってもなくても良い -->
      </number_become_aho>
      <number_not_aho>
        <xsl:apply-templates select="number[not(@aho)]"/>
      </number_not_aho>
    </root>
  </xsl:template>

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

実行:

$ java -jar $saxon_home/saxon9.jar -versionmsg:off -s:aho01.xml -xsl:aho01.xsl

実行結果:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <number_become_aho>
      <number>3</number>
      <number>6</number>
      <number>9</number>
      <number>12</number>
      <number>13</number>
      <number>15</number>
   </number_become_aho>
   <number_not_aho>
      <number>1</number>
      <number>2</number>
      <number>4</number>
      <number>5</number>
      <number>7</number>
      <number>8</number>
      <number>10</number>
      <number>11</number>
      <number>14</number>
   </number_not_aho>
</root>

属性値の判定

3の倍数と3がつく数字のときにアホになるxmlを次のように変えよう(aho02.xml).アホになる数字には属性ahoにtrue,アホにならない数字にはfalseを設定する.

aho2.xml:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <number aho="false">1</number>
    <number aho="false">2</number>
    <number aho="true">3</number>
    <number aho="false">4</number>
    <number aho="false">5</number>
    <number aho="true">6</number>
    <number aho="false">7</number>
    <number aho="false">8</number>
    <number aho="true">9</number>
    <number aho="false">10</number>
    <number aho="false">11</number>
    <number aho="true">12</number>
    <number aho="true">13</number>
    <number aho="false">14</number>
    <number aho="true">15</number>
</root>

このxmlに前出のaho01.xslを適応すると,全ての数字でアホになる.

実行結果:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <number_become_aho>
      <number>1</number>
      <number>2</number>
      <number>3</number>
      <number>4</number>
      <number>5</number>
      <number>6</number>
      <number>7</number>
      <number>8</number>
      <number>9</number>
      <number>10</number>
      <number>11</number>
      <number>12</number>
      <number>13</number>
      <number>14</number>
      <number>15</number>
   </number_become_aho>
   <number_not_aho/>
</root>

<xsl:apply-templates select="number[@aho]"/>は属性ahoがあればtrue,なければfalseであり,属性ahoに入っている値(true/false)は真偽値に影響しないためである.3の倍数と3がつく数字のときにアホになるためにxslを以下のように書換える.

aho02.xsl

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output
    method="xml"
    encoding="UTF-8"
    indent="yes"/>

  <xsl:template match="/root">
    <root>
      <number_become_aho>
        <xsl:apply-templates select="number[@aho='true']"/> <!-- 属性ahoの値がtrueだったら -->
      </number_become_aho>
      <number_not_aho>
        <xsl:apply-templates select="number[@aho='false']"/>  <!-- 属性ahoの値がfalseだったら -->
      </number_not_aho>
    </root>
  </xsl:template>

  <xsl:template match="number">
    <number>
      <xsl:value-of select="."/>
    </number>
  </xsl:template>
</xsl:stylesheet>

実行結果:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <number_become_aho>
      <number>3</number>
      <number>6</number>
      <number>9</number>
      <number>12</number>
      <number>13</number>
      <number>15</number>
   </number_become_aho>
   <number_not_aho>
      <number>1</number>
      <number>2</number>
      <number>4</number>
      <number>5</number>
      <number>7</number>
      <number>8</number>
      <number>10</number>
      <number>11</number>
      <number>14</number>
   </number_not_aho>
</root>

属性値の有無

xmlを更に変えてみよう(aho03.xml).アホになる数字には属性値ahoにtrue,アホにならない数字には空文字列が入っている.

aho03.xml:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <number aho="">1</number>
    <number aho="">2</number>
    <number aho="true">3</number>
    <number aho="">4</number>
    <number aho="">5</number>
    <number aho="true">6</number>
    <number aho="">7</number>
    <number aho="">8</number>
    <number aho="true">9</number>
    <number aho="">10</number>
    <number aho="">11</number>
    <number aho="true">12</number>
    <number aho="true">13</number>
    <number aho="">14</number>
    <number aho="true">15</number>
</root>

空文字列はfalseとなることを利用して属性ahoを文字列に変換して判断できる.

aho03.xsl:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output
    method="xml"
    encoding="UTF-8"
    indent="yes"/>

  <xsl:template match="/root">
    <root>
      <number_become_aho>
        <xsl:apply-templates select="number[string(@aho)]"/> <!-- 空文字以外はtrue -->
      </number_become_aho>
      <number_not_aho>
        <xsl:apply-templates select="number[not(string(@aho))]"/> <!-- 空文字列はfalse -->
      </number_not_aho>
    </root>
  </xsl:template>

  <xsl:template match="number">
    <number>
      <xsl:value-of select="."/>
    </number>
  </xsl:template>
</xsl:stylesheet>

実行結果:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <number_become_aho>
      <number>3</number>
      <number>6</number>
      <number>9</number>
      <number>12</number>
      <number>13</number>
      <number>15</number>
   </number_become_aho>
   <number_not_aho>
      <number>1</number>
      <number>2</number>
      <number>4</number>
      <number>5</number>
      <number>7</number>
      <number>8</number>
      <number>10</number>
      <number>11</number>
      <number>14</number>
   </number_not_aho>
</root>

ついでにテキストノードの場合

アホになるかならないかが属性ではなくテキストノードに書いてある場合を考えてみた.

aho10.xml:

<?xml version="1.0" encoding="UTF-8"?>
<root>
    <number value="1"/>
    <number value="2"/>
    <number value="3">aho</number>
    <number value="4"/>
    <number value="5"/>
    <number value="6">aho</number>
    <number value="7"/>
    <number value="8"/>
    <number value="9">aho</number>
    <number value="10"/>
    <number value="11"/>
    <number value="12">aho</number>
    <number value="13">aho</number>
    <number value="14"/>
    <number value="15">aho</number>
</root>

aho10.xsl:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">

  <xsl:output
    method="xml"
    encoding="UTF-8"
    indent="yes"/>

  <xsl:template match="/root">
    <root>
      <number_become_aho>
        <xsl:apply-templates select="number[text()]"/>
        <!-- これでもOK
        <xsl:apply-templates select="number[.!='']"/>
        <xsl:apply-templates select="number[.='aho']"/> -->
      </number_become_aho>
      <number_not_aho>
        <xsl:apply-templates select="number[not(text())]"/>
        <!-- これでもOK
        <xsl:apply-templates select="number[.='']"/>
        <xsl:apply-templates select="number[.!='aho']"/> -->
      </number_not_aho>
    </root>
  </xsl:template>

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

実行結果:

<?xml version="1.0" encoding="UTF-8"?>
<root>
   <number_become_aho>
      <number value="3">aho</number>
      <number value="6">aho</number>
      <number value="9">aho</number>
      <number value="12">aho</number>
      <number value="13">aho</number>
      <number value="15">aho</number>
   </number_become_aho>
   <number_not_aho>
      <number value="1"/>
      <number value="2"/>
      <number value="4"/>
      <number value="5"/>
      <number value="7"/>
      <number value="8"/>
      <number value="10"/>
      <number value="11"/>
      <number value="14"/>
   </number_not_aho>
</root>

まとめ

属性の有無

xml:

<number>1</number>
<number>2</number>
<number aho="true">3</number>

xsl:

<xsl:apply-templates select="number[@aho]"/>
<xsl:apply-templates select="number[not(@aho)]"/>

属性値の判定

xml:

<number aho="false">1</number>
<number aho="false">2</number>
<number aho="true">3</number>

xsl:

<xsl:apply-templates select="number[@aho='true']"/>
<xsl:apply-templates select="number[@aho='false']"/>

属性値の有無

xml:

<number aho="">1</number>
<number aho="">2</number>
<number aho="true">3</number>

xsl:

<xsl:apply-templates select="number[string(@aho)]"/>
<xsl:apply-templates select="number[not(string(@aho))]"/>

テキストノード

xml:

<number value="1"/>
<number value="2"/>
<number value="3">aho</number>

xsl:

<xsl:apply-templates select="number[text()]"/>
<xsl:apply-templates select="number[not(text())]"/>