DTD

属性のデフォルト値

このエントリーをはてなブックマークに追加
最終更新日 2016-12-31

XmlLite は、XML Schema や DTD を使用したドキュメント検証はサポートしませんが、 DTD による外部エンティティの解決および属性のデフォルト値はサポートします。

次に示すのは、属性のデフォルト値を読み込む例です。 あらかじめ sample.xml というファイルをプログラムと同じフォルダに用意しておき、 XML を読み込んだ結果をメッセージボックスに表示します。

プロジェクトファイル ダウンロード

// sample.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sample [
  <!ATTLIST name type CDATA "ヘッダ">
]>
<sample>
  <requirement>
    <name>XmlLite.h</name>
  </requirement>
  <requirement>
    <name type="ライブラリ">XmlLite.lib</name>
  </requirement>
</sample>
// stdafx.h
#pragma once

#include "targetver.h"

#define WIN32_LEAN_AND_MEAN
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS

#include <atlbase.h>  // CComPtrを使用するため
#include <atlstr.h>   // CStringを使用するため

#include <xmllite.h>
#pragma comment(lib, "xmllite.lib")
// SampleProject.cpp
#include "stdafx.h"

void Run()
{
    CComPtr<IXmlReader> pReader;
    if(FAILED(CreateXmlReader(__uuidof(IXmlReader), reinterpret_cast<void**>(&pReader), 0))){
        MessageBox(NULL, _T("CreateXmlReader失敗"), _T("警告"), MB_OK | MB_ICONWARNING);
        return;
    }

    // XMLファイルパス作成
    TCHAR xml[MAX_PATH];
    GetModuleFileName(NULL, xml, sizeof(xml) / sizeof(TCHAR));
    PathRemoveFileSpec(xml);
    PathAppend(xml, _T("sample.xml"));

    // ファイルストリーム作成
    CComPtr<IStream> pStream;
    if(FAILED(SHCreateStreamOnFile(xml, STGM_READ, &pStream))){
        MessageBox(NULL, _T("SHCreateStreamOnFile失敗"), _T("警告"), MB_OK | MB_ICONWARNING);
        return;
    }

    if(FAILED(pReader->SetInput(pStream))){
        MessageBox(NULL, _T("SetInput失敗"), _T("警告"), MB_OK | MB_ICONWARNING);
        return;
    }

    if(FAILED(pReader->SetProperty(XmlReaderProperty_DtdProcessing, DtdProcessing_Parse))){
        MessageBox(NULL, _T("SetProperty失敗"), _T("警告"), MB_OK | MB_ICONWARNING);
        return;
    }

    CString result;
    CString type;
    LPCWSTR pwszLocalName;
    LPCWSTR pwszValue;
    XmlNodeType nodeType;
    HRESULT hr;
    while(S_OK == pReader->Read(&nodeType)){
        switch(nodeType){
        case XmlNodeType_Element:
            if(FAILED(pReader->GetLocalName(&pwszLocalName, NULL))){
                MessageBox(NULL, _T("GetLocalName失敗"), _T("警告"), MB_OK | MB_ICONWARNING);
                return;
            }

            hr = pReader->MoveToFirstAttribute();

            // 属性が無い
            if(S_FALSE == hr){
                break;
            }

            if(S_OK != hr){
                MessageBox(NULL, _T("MoveToFirstAttribute失敗"), _T("警告"), MB_OK | MB_ICONWARNING);
                return;
            }

            do{
                LPCWSTR pwszAttributeName;
                LPCWSTR pwszAttributeValue;
                if(FAILED(pReader->GetLocalName(&pwszAttributeName, NULL))){
                    MessageBox(NULL, _T("GetLocalName失敗"), _T("警告"), MB_OK | MB_ICONWARNING);
                    return;
                }
                if(FAILED(pReader->GetValue(&pwszAttributeValue, NULL))){
                    MessageBox(NULL, _T("GetValue失敗"), _T("警告"), MB_OK | MB_ICONWARNING);
                    return;
                }
                if(lstrcmp(pwszAttributeName, _T("type")) == 0){
                    type.Format(_T("種類:%s"), pwszAttributeValue);
                    if(pReader->IsDefault()){
                        type += _T("(デフォルト値)\n");
                    }else{
                        type += _T("(非デフォルト値)\n");
                    }
                }
            }while(S_OK == pReader->MoveToNextAttribute());
            break;
        case XmlNodeType_Text:
            if(FAILED(pReader->GetValue(&pwszValue, NULL))){
                MessageBox(NULL, _T("GetValue失敗"), _T("警告"), MB_OK | MB_ICONWARNING);
                return;
            }
            if(lstrcmp(pwszLocalName, _T("name")) == 0){
                result += type;
                CString name;
                name.Format(_T("名前:%s\n\n"), pwszValue);
                result += name;
            }
            break;
        }
    }

    MessageBox(NULL, result, _T("結果"), MB_OK | MB_ICONINFORMATION);
}

int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    Run();

    return 0;
}

DTD を有効にするためには、IXmlReader::SetProperty() を呼び出して XmlReaderProperty_DtdProcessing に DtdProcessing_Parse を設定します。 DTD を有効にすると、XmlLite は属性のデフォルト値をサポートするようになります。 今回の例では <name> 要素に type 属性が無い場合に、type 属性にデフォルト値として "ヘッダ" という文字列を設定します。 XmlLite は属性が DTD によるデフォルト値かどうかを判定するために IXmlReader::IsDefault() を用意しています。