HTTPサーバーとWeb開発

69. XML禁則文字とは ?

XMLで、使用してはならない禁則文字というのがあるのをご存知だろうか ?
XML での禁則文字を使用するとブラウザは無反応になってしまい、
JavaScript のエラーも発生していない予期しない結果となって解決に手間取ることになって
しまう。
XMLの禁則文字とは、

     &  <  >  "   '

の 5つの文字である。これらの文字がそのまま XML上に混入されていると XMLパーサーや
DOM が誤動作を起こして無反応になっていまうのである。
Ajax でも XMLを結果として返すことが多いので、これらには注意しなくてはならない。
それではこれらの禁則文字を表示したいときは、どのようにすれば良いのかをここで
紹介する。
例えば & は & だけで表示するのではなく

      &amp;

というようにコード化して表示すると XMLビューア上では「&」と正しく表示することができる。
この対応表を以下に紹介する。

XML禁則文字コード化表現
&&amp;
<&lt;
>>&gt;
"&quot;
'&apos;

これだけ意識して XMLのコード変換をすればよいかというと、そう簡単な話ではない。
漢字の一部には、これらの禁則文字が 1バイトとして混ざっている場合があり、
上記のコードが見つかればすべてコード化してしまうと、今度は漢字が正しく表示されなく
なってしまうからである。
そこで半角文字の XML禁則文字の場合だけをコード化表現するようにしなければならない。

次に C/400で書かれた XMLの禁則文字を正しくコード化する関数のソースを紹介する。
この関数は eStudio でコンバイルを実行したときのコンパイル・リストを XML で
ブラウザに戻す場合に使用されている。
コンパイル・リスト中ではどのような文字が発生しても XML禁則文字があれば
この関数によって正しくコード化されてブラウザ上に正しい表現で表示される。
もちろんユーザーが RPGエンジンで使用する
「 AddXML プロシージャー 」にも、この関数は利用されていて、開発者が意識しなくても
コード化表現が内部で行われるようになっている。

ソースコード
----------------------------------------------------------------
/**************************/                                 
void  encodeXML(char* buff)                                  
/**************************/                                 
{                                                            
   int   pos, len, i, j, bKJ;                                
   char  new_buff[2048];                                     
                                                             
   memset(new_buff, 0, sizeof(new_buff));                    
   len = strlen(buff);                                       
   j = 0;                                                    
   bKJ = FALSE;                                              
   for(i = 0; i<len; i++){/*for-loop*/                       
     if(bKJ == FALSE){/* まだ漢字でない */                   
       if(buff[i] == 0x0e){/* シフト始め */                  
         bKJ = TRUE;                                         
       }/* シフト始め */                                     
       else{/* 半角 */                                       
         switch(buff[i]){/*switch*/                          
         case '&':  memcpy(&new_buff[j], "&", 5); j += 5;
                    continue;                                
         case '<':  memcpy(&new_buff[j], "<", 4);  j += 4;
                    continue;                                
         case '>':  memcpy(&new_buff[j], ">", 4);  j += 4;   
                    continue;                                   
         case '"':  memcpy(&new_buff[j], """, 6);  j += 6; 
                    continue;                                   
         case '\'': memcpy(&new_buff[j], "'", 6);  j += 6; 
                    continue;                                   
         default:   break;                                      
         }/*switch*/                                            
       }/* 半角 */                                              
     }/* まだ漢字でない */                                      
     else{/* 漢字中 */                                          
       if(buff[i] == 0x0f){/* シフト終わり */                   
         bKJ = FALSE;                                           
       }/* シフト終わり */                                      
     }/* 漢字中 */                                              
     new_buff[j] = buff[i];                                     
     j ++;                                                      
   }/*for-loop*/                                                
   memcpy(buff, new_buff, j);                                   
                                                                
}                                                               
----------------------------------------------------------------