ホーム > デベロッパ > SophiaFramework > BREW C++ 逆引きコード集

BREW C++ プログラミング 逆引きコード集 : WSDL / SOAP / XML

C++ で作成されたBREW アプリで、XMLを扱う方法です。
SophiaFramework を用いています。

DOM パーサーを使って SOAP 文書を解析する

SFXSOAPParser::Parse を使って、XML 文書を読み込み、解析します。

SFXSOAPParser クラスは SFXXMLDOMParser クラスを継承します。

// 解析対象の XML 文書( "soapmessage.xml" )
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope" >
 <env:Header>
    <SubscriptionInfo xmlns="http://schemas.xmlsoap.org">
      <LicenseStatusCode>0</LicenseStatusCode>
      <LicenseStatus>Valid license key</LicenseStatus>
      <LicenseActionCode>0</LicenseActionCode>
      <LicenseAction>Decremented hit count</LicenseAction>
      <RemainingHits>18</RemainingHits>
      <Amount>0</Amount>
    </SubscriptionInfo>
 </env:Header>
 <env:Body>
  <m:GetLastTradePriceResponse 
        env:encodingStyle="http://www.w3.org/2003/05/soap-envelope"
        xmlns:m="http://example.org/2001/06/quotes">
   <Price>34.5</Price>
  </m:GetLastTradePriceResponse>
  <m:GetLastTradePriceResponse
        env:encodingStyle="http://www.w3.org/2003/05/soap-envelope"
        xmlns:m="http://example.org/2006/06/quotes">
   <Price>56.5</Price>
  </m:GetLastTradePriceResponse>
 </env:Body>
</env:Envelope>

SOAP 文書の解析のサンプルコードです。

SFXSOAPParser soapparser; // SOAP パーサー

// SOAP 文書を読み込み、解析する
// soapmessage.xml に保存した SOAP 文書を解析する
if  (soapparser.Parse("soapmessage.xml") != SFERR_NO_ERROR) {

    // エラーコードを表示する
    TRACE("error id = 0x%x", soapparser.static_catch());

    // エラーメッセージを表示する
    TRACE(soapparser.GetErrorInfo());

// 解析が完了したら行う処理を記述する
} else {

    // SOAP 文書のバージョンを取得し表示する
    // SOAP メッセージのバージョンは SFXSOAPParser::SOAP_VERSION_1_2 になる
     // soap version : 1
    TRACE("soap version : %d", soapparser.GetSoapVersion()); 

    // Envelope 要素を取得する
    SFXXMLElementPtr envelope = soapparser.GetEnvelope();

    // Envelope 要素の名前空間を取得する
    // envelope version : http://www.w3.org/2003/05/soap-envelope
    TRACE("envelope version : %s", envelope->GetNamespaceURI());  

    // Header 要素を取得する
    SFXXMLElementPtr header = soapparser.GetHeader();
    // Header 要素の名前空間を取得する
    // header version : http://www.w3.org/2003/05/soap-envelope
    TRACE("header version : %s", header->GetNamespaceURI());  

    / SOAP メッセージの Header の中のすべてのエントリーノードを取得する
    SFXXMLNode::DOMNodeListPtr list = soapparser.GetHeaderEntries();

    // 要素数の取得し表示する
    // entry number : 1
    TRACE("entry number : %d", list->GetSize());  

    // エントリーノードを取得する
    SFXXMLElementPtr entry = soapparser.GetHeaderEntry("SubscriptionInfo", "http://schemas.xmlsoap.org");

    // エントリーノードのすべての子を取得する
    list = entry->GetChildNodes();

    // 列挙子を取得する
    SFXXMLNode::DOMNodeList::Enumerator childiter = list->GetFirstEnumerator();

    while (childiter.HasNext()) {

        SFXXMLElementPtr current = static_cast<SFXXMLElementPtr>(childiter.GetNext());

        // 各要素の名前を取得し表示する
        // current element name : "LicenseStatusCode" "LicenseStatus" "LicenseActionCode" "RemainingHits" "Amount"
        TRACE("current element name : %s", current->GetName());  
        
        // 各要素の文字列を取得し表示する
        // current element content : "0" "Valid license key" "0" "Decremented hit count" "18" "0"
        TRACE("current element content : %s", current->GetText().GetCString()); 
    }

    // SOAP メッセージの Body 要素を取得する
    SFXXMLElementPtr body = soapparser.GetBody();

    // Body 要素の名前空間を取得する
    // body version : http://www.w3.org/2003/05/soap-envelope
    TRACE("body version : %s", body->GetNamespaceURI());   

    // SOAP メッセージの Body の中に持つすべてのエントリーノードを取得する
    list = soapparser.GetBodyEntries();

    // 要素数の取得し表示する
    TRACE("entry number: %d", list->GetSize());  // 2

   // 列挙子を取得する
    childiter = list->GetFirstEnumerator();

    while (childiter.HasNext()) {

        SFXXMLElementPtr current = static_cast<SFXXMLElementPtr>(childiter.GetNext());

        // 各要素内容を取得し表示する
        // current element name : "GetLastTradePriceResponse" "GetLastTradePriceResponse"
        TRACE("current element name : %s", current->GetLocalName()); 
        // 各要素の名前空間を取得し表示する
        // current element namespace : "http://example.org/2001/06/quotes" "http://example.org/2006/06/quotes"
        TRACE("current element namespace : %s", current->GetNamespaceURI()); 

        // 価格を取得し表示する
        // price : "34.5" "56.5"
        TRACE("price : %s", current->GetText().GetCString());  
    }
}
      

指定したタグ名を持つ、すべてのノードを取得する

SFXXMLElement::GetElementsByTagName メソッドを使って指定したタグ名を持つ、すべてのノードを取得します。

解析対象の XML 文書( file.xml )
<fruits>
    <fruit>
        <name>apple</name>
        <size>XS</size>
        <color>red</color>
    </fruit>
    <fruit>
        <name>banana</name>
        <size>S</size>
        <color>yellow</color>
    </fruit>
    <fruit>
        <name>melon</name>
        <size>XS</size>
        <color>green</color>
    </fruit>
</fruits>
サンプルコード
SFCError error;             // エラー値
SFXXMLDOMParser parser;     // DOM パーサー
SFXAnsiString resultString; // 結果を格納する文字列

// file.xml に保存した XML 文書を解析する
if ((error = parser.Parse("/file.xml")) == SFERR_NO_ERROR) {
    // ルート要素を取得する
    SFXXMLDocumentPtr root = parser.GetDocument(); 
    // ルート要素の最初の子要素 ( "fruits" 要素 ) を取得する
    SFXXMLNodePtr child = root->GetFirstChild();  
    // 要素 ( "fruit" 要素 ) を取得する
    SFXXMLNodePtr node = child->GetFirstChild();

    // "fruit" 要素のすべての子要素を取得する
    // SFXXMLNode::DOMNodeListPtr は SFXList<SFXXMLNodePtr> と同じ
    SFXXMLNode::DOMNodeListPtr nodeList = node ->GetChildNodes();
    // イテレータを取得する
    SFXXMLNode::DOMNodeList::Iterator itor = nodeList->GetFirstIterator();   
    // color 要素を持つ全要素を取得する
    nodeList = static_cast<SFXXMLElementPtr>(child)->GetElementsByTagName("color"); 
    // イテレータを取得する
    itor = nodeList->GetFirstIterator(); 

    while (itor.HasNext()) { // 次の要素があるかぎり繰り返す
        // 次の要素を取得する
        SFXXMLNodePtr node = itor.GetNext();     
        // 要素のテキストを取得する
        resultString = node->GetText();      
        // 要素のテキストを表示する
        TRACE("%s",resultString.GetCString());  // "red" "yellow" "green"
    }
}
      

複数の DOM ノードを名前で管理する

SFXXMLNode::DOMNamedNodeMap クラスを使って、複数の DOM ノードをリストで名前します。

解析対象の XML 文書(file.xml)
<fruit>
    <name made="japan" date="2007-06-20"size="XS">apple</name>
</fruit>
SFXXMLNode::DOMNamedNodeMap クラスを使ったサンプルコード
SFCError error;             // エラー値
SFXXMLDOMParser parser;     // DOM パーサー
SFXAnsiString resultString; // 結果を格納する文字列

// file.xml に保存した XML 文書を解析する
if ((error = parser.Parse("/file.xml")) == SFERR_NO_ERROR) {
    // ルート要素を取得する
    SFXXMLDocumentPtr root = parser.GetDocument();   
    / ルート要素の最初の子要素 ( "fruit" 要素 ) を取得する
    SFXXMLNodePtr child = root->GetFirstChild();  
    // "fruit"要素の子要素 ( "name" 要素 )を取得する
    child = child->GetFirstChild();                

    // すべての Attribute ノードを取得し、名前で管理する
    SFXXMLNode::DOMNamedNodeMapPtr nodeMap = SFXXMLElementPtr(child)->GetAttributes();

    //  マップのノード数を表示する
    TRACE("%d",nodeMap->GetLength());  // 3

    for (int i = 0; i < nodeMap->GetLength(); i++) {
        // マップの index 番目の項目を取得する
        SFXXMLNodePtr node = nodeMap->Item(i); 
       // マップの index 番目の項目のノードの値を取得する
        resultString = node->GetNodeValue();   

        // 取得したノードの値を表示する
        TRACE("%s",resultString.GetCString()); // "XS" "2007-06-20" "japan"
    }
    
   / 名前により指定されたノード(  "date " )を取得する
    SFXXMLAttributePtr date = static_cast<SFXXMLAttributePtr>(nodeMap->GetNamedItem( "date "));
    // 名前により指定されたノード(  "date " )の値を取得する
    resultString = date->GetNodeValue();   
	
    // 取得したノードの値を表示する
    TRACE("%s",resultString.GetCString()); // "2007-06-20"
    
    // 名前で指定したノード( "made" )を削除する
    SFXXMLNodePtr remove = nodeMap->RemoveNamedItem("made");
    // ノード ポインターを削除する
    ::delete remove;
	
    //  マップのノード数を表示する
    TRACE("%d",nodeMap->GetLength());  // 2
    
    for (int i = 0; i < nodeMap->GetLength(); i++) {
        // マップの index 番目の項目を取得する
        SFXXMLNodePtr node = nodeMap->Item(i); 
        // マップの index 番目の項目のノードの値を取得する
        resultString = node->GetNodeValue();   

        // 取得したノードの値を表示する
        TRACE("%s",resultString.GetCString());   // "XS" "2007-06-20"
    }
    
    // 特定のノードをその nodeName 属性を使って追加する
    nodeMap->SetNamedItem(root->CreateAttribute("color", "red"));
    
    //  マップのノード数を表示する
    TRACE("%d",nodeMap->GetLength());   // 3
    
    for (int i = 0; i < nodeMap->GetLength(); i++) {
        // マップの index 番目の項目を取得する
        SFXXMLNodePtr node = nodeMap->Item(i); 
        // マップの index 番目の項目のノードの値を取得する
        resultString = node->GetNodeValue();   

        // 取得したノードの値を表示する
        TRACE("%s",resultString.GetCString());  // "XS" "2007-06-20" "red"
    }
}
      

複数の DOM ノードをリストで管理する

SFXXMLNode::DOMNodeList クラスを使って、複数の DOM ノードをリストで管理します。

解析対象の XML 文書(file.xml)
<fruit>
  <name>apple</name>
  <size>XS</size>  
  <color>red</color>
</fruit>
SFXXMLNode::DOMNodeList からすべての要素を取得するサンプルコード
SFCError error;             // エラー値
SFXXMLDOMParser parser;     // DOM パーサー
SFXAnsiString resultString; // 結果を格納する文字列

// file.xml に保存した XML 文書を解析する
if ((error = parser.Parse("/file.xml")) == SFERR_NO_ERROR) {

    // ルート要素を取得する
    SFXXMLDocumentPtr root = parser.GetDocument(); 
    // ルート要素の最初の子要素 ( "fruit" 要素 ) を取得する
    SFXXMLNodePtr child = root->GetFirstChild();   

    // "fruit" 要素のすべての子要素を取得する
    // SFXXMLNode::DOMNodeListPtr は SFXList と同じ
    SFXXMLNode::DOMNodeListPtr nodeList = child->GetChildNodes();

    // イテレータを取得する
    SFXXMLNode::DOMNodeList::Iterator itor = nodeList->GetIterator();

    while (itor.HasNext()) { // 次の要素があるかぎり繰り返す

        // "name"要素、"size"要素、"color" 要素の順に取得できる
        SFXXMLNodePtr node = itor.GetNext();

        // 要素の名前を取得する
        resultString = node->GetNodeName();

        // 要素のテキストを取得する
        // "name" の場合は "apple"、"size" の場合は "XS" 
        resultString = node->GetText();
        // 要素のテキストを表示する
        TRACE("%s",resultString.GetCString());
    }
}
      

XML 文書を作成する

SFXXMLDocument クラスを使って、 XML 文書を作成します。

SFCError error; // エラー値

// XML 文書を作成する
SFXXMLDocument document;

// XML 文書のバージョンを設定する
document.SetVersion("1.0");
// COLLECTION 要素を作成する
SFXXMLElementPtr boot = document.CreateElement("COLLECTION");
if (boot == null) {
    return;
}
// ルート要素に COLLECTION 要素を追加する
error = document.AppendChild(SFXXMLNodePtr(boot));
if (error != SFERR_NO_ERROR) {
    return;
}
// COLLECTION 要素に属性を追加する
boot->SetAttribute("xmlns:dt", "urn:schemas-microsoft-com:datatypes");
// DATE 要素を作成する
SFXXMLElementPtr element = document.CreateElement("DATE");
if (element == null) {
    return;
}
// DATE 要素の属性を追加する
element->SetAttribute("dt:dt", "datetime");
// DATE 要素のテキスト情報を追加する
error = element->AppendChild(SFXXMLNodePtr(
    document.CreateTextNode("1998-10-13T15:56:00")));
if (error != SFERR_NO_ERROR) {
    return;
}
// COLLECTION 要素に DATE 要素を追加する
error = boot->AppendChild(SFXXMLNodePtr(element));
if (error != SFERR_NO_ERROR) {
    return;
}
// BOOK 要素を作成する
SFXXMLElementPtr book = document.CreateElement("BOOK");
if (book == null) {
    return;
}
// COLLECTION 要素に BOOK 要素を追加する
error = boot->AppendChild(SFXXMLNodePtr(book));
if (error != SFERR_NO_ERROR) {
    return;
}

// "<TITLE>Cosmos</TITLE>" を作成する
element = document.CreateElement("TITLE");
if (element == null) {
    return;
}
error = element->AppendChild(SFXXMLNodePtr(document.CreateTextNode("Cosmos")));
if (error != SFERR_NO_ERROR) {
    return;
}
error = book->AppendChild(SFXXMLNodePtr(element));
if (error != SFERR_NO_ERROR) {
    return;
}
// "<AUTHOR>Carl Sagan</AUTHOR>" を作成する
element = document.CreateElement("AUTHOR");
if (element == null) {
    return;
}
error = element->AppendChild(SFXXMLNodePtr(document.CreateTextNode("Carl Sagan")));
if (error != SFERR_NO_ERROR) {
    return;
}
error = book->AppendChild(SFXXMLNodePtr(element));
if (error != SFERR_NO_ERROR) {
    return;
}
// "<PUBLISHER>Ballantine Books</PUBLISHER>" を作成する
element = document.CreateElement("PUBLISHER");
if (element == null) {
    return;
}
error = element->AppendChild(SFXXMLNodePtr(document.CreateTextNode("Ballantine Books")));
if (error != SFERR_NO_ERROR) {
    return;
}
error = book->AppendChild(SFXXMLNodePtr(element));
if (error != SFERR_NO_ERROR) {
    return;
}
// XML 文書を保存する
error = document.Save("book.xml");
if (error != SFERR_NO_ERROR) {
    return;
}
作成した XML 文書
<?xml version='1.0'?>
<COLLECTION
   xmlns:dt="urn:schemas-microsoft-com:datatypes">
  <DATE dt:dt="datetime">1998-10-13T15:56:00</DATE>
  <BOOK>
    <TITLE>Cosmos</TITLE>
    <AUTHOR>Carl Sagan</AUTHOR>
    <PUBLISHER>Ballantine Books</PUBLISHER>
  </BOOK>
</COLLECTION>
      

SOAP メッセージを作成する

SFXSOAPWriter クラスを使って、SOAP メッセージを作成します。

SFXSOAPWriter soapwriter;   // SOAP メッセージの各要素を生成するオブジェクト
SFCError      error;        // エラー値を保存する変数

// Envelope 要素を作成する
// 名前空間接頭辞は明示的に設定しないと、"SOAP-ENV" になる
SFXXMLElementPtr envelope = soapwriter.SetEnvelope("env", SFXSOAPParser::SOAP_VERSION_1_2, "STANDARD ");

// Header 要素と Body 要素を作成する
if (envelope) {
    // xmlns:m= "http://www.example.org/timeouts" 名前空間を追加する
    error = soapwriter.AddNamespace(envelope, "m", "http://www.example.org/timeouts");
    // 名前空間が追加されているか確認する
    if(error != SFERR_NO_ERROR){
         TRACE("-----Envelope_NAMESPACE_ERROR:%d-----", error);
    }
    // Fault 要素の設定 ( デフォルトでは Body 要素の子要素となる )
    soapwriter.SetFault("testing-fault-code","testing-fault-string"
                        ,"testing-fault-actor");
    // Fault 要素のエラー詳細内容の設定
    soapwriter.SetFaultDetail("STANDARD")
                                      ->SetText("testing-fault-detail-message");
    // Header 要素の設定
    SFXXMLElementPtr header = soapwriter.SetHeader();
    if (header) {
        // isbn:bookname="サッカー ワールド カップ" 属性を追加する
        error = soapwriter.AddAttribute(header, "bookname",
                      "http://www.example.com/ISBN", 
                      "サッカー ワールド カップ", "isbn");
        // 属性が追加されているか確認する
        if(error != SFERR_NO_ERROR){
            TRACE("-----HEADER_ATTRIBUTE_ERROR:%d-----", error);
        }        
        // xmlns:isbn="http://www.example.com/ISBN" 名前空間を追加する
        error = soapwriter.AddNamespace(header, "isbn", "http://www.example.com/ISBN");
        // 名前空間が追加されているか確認する
        if(error != SFERR_NO_ERROR){
            TRACE("-----HEADER_NAMESPACE_ERROR:%d-----", error);
        }
        // Header 要素の子要素 Upgrade を追加する
        // Upgrade 要素の名前空間は Header 要素と同じものに設定する
        SFXXMLElementPtr elem = soapwriter.SetElement(header, "Upgrade", header->GetNamespaceURI(), header->GetPrefix());
        if (elem) {
            // Upgrade 要素の子要素 SupportedEnvelope を設定する
            elem = soapwriter.SetElement(elem, "SupportedEnvelope", header->GetNamespaceURI(), header->GetPrefix());
            // SupportedEnvelope 要素の属性を追加する
            error = soapwriter.AddAttribute(elem, "qname", "http://schemas.xmlsoap.org/soap/envelope/", "ns1:Envelope");
            // 要素の属性が追加されているか確認する
            if(error != SFERR_NO_ERROR){
                TRACE("-----UPGRADE_ATTRIBUTE_ERROR:%d-----", error);
            }      
            // SupportedEnvelope 要素の名前空間を追加する
            error = soapwriter.AddNamespace(elem, "ns1", "http://schemas.xmlsoap.org/soap/envelope/");   
            // 要素の名前空間が追加されているか確認する
            if(error != SFERR_NO_ERROR){
                TRACE("-----UPGRADE_NAMESPACE_ERROR:%d-----", error);
            }
        }
    }
    // 作成した SOAP メッセージを保存する
    error = soapwriter.Save("soapwriter.xml");
    // 保存されているか確認する
    if(error != SFERR_NO_ERROR){
        TRACE("-----SOAP_SAVE_ERROR:%d-----", error);
    }
}
作成した SOAP メッセージ
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope"
              env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
              xmlns:m="http://www.example.org/timeouts">
    <env:Header isbn:bookname="サッカー ワールド カップ" xmlns:isbn="http://www.example.com/ISBN">
       <env:Upgrade>
           <env:SupportedEnvelope qname="ns1:Envelope" xmlns:ns1="http://schemas.xmlsoap.org/soap/envelope/"/>
        </env:Upgrade>
    </env:Header>
    <env:Body>
       <env:Fault>
           <faultcode>testing-fault-code</faultcode>
            <faultstring>testing-fault-string</faultstring>
            <faultactor>testing-fault-actor</faultactor>
            <detail env:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">testing-fault-detail-message</detail>
       </env:Fault>
    </env:Body>
</env:Envelope>
      

SAX パーサーを使って XML 文書を解析する

SFXXMLSAXParser::Parse を使って、XML 文書を読み込み、解析します。

SFXXMLSAXParser クラスを使うには、 SFXXMLDefaultHandler クラスを継承するクラスを実装する必要があります。

XML文書を解析するサンプルコード
SFXXMLSAXParser saxparser;
MyXMLHandler handler;

// イベントを通知するハンドラ インターフェースを設定する
saxparser.SetDefaultHandler(&handler);

// パーサーを開始する
// アプリのホームフォルダにある file.xml を解析する
saxparser.Parse("file.xml");
ハンドラ クラスの定義( SFXXMLDefaultHandler クラスを継承するクラス )
class MyXMLHandler : public SFXXMLDefaultHandler {
public:
    explicit MyXMLHandler(Void);
    virtual ~MyXMLHandler(Void);

    // 各ハンドラ
    virtual Void Characters(SFXAnsiStringConstRef string, BoolConst cdataSection = true);
    virtual Void EndDocument(Void);
    virtual Void EndElement(SFXAnsiStringConstRef uri =SFXAnsiString::EmptyInstance(),
        SFXAnsiStringConstRef localname = SFXAnsiString::EmptyInstance(),
        SFXAnsiStringConstRef qname = SFXAnsiString::EmptyInstance());
    virtual Void StartDocument(Void);
    virtual Void StartElement(SFXAnsiStringConstRef uri,
        SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname,
        SFXXMLGrammar::XMLAttrListConstRef attrList);
    virtual Void IgnorableWhitespace(SFXAnsiStringConstRef string);
    virtual Void ProcessingInstruction(SFXAnsiStringConstRef target,
        SFXAnsiStringConstRef data);
    virtual Void EndPrefixMapping(SFXAnsiStringConstRef  prefix);
    virtual Void StartPrefixMapping(SFXAnsiStringConstRef prefix,
        SFXAnsiStringConstRef uri);

    virtual Void Comment(SFXAnsiStringConstRef string);
    virtual Void EndCDATA(Void);
    virtual Void EndDTD(Void);
    virtual Void EndEntity(SFXAnsiStringConstRef name);
    virtual Void StartCDATA(Void);
    virtual Void StartDTD(SFXAnsiStringConstRef name,
        SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId);
    virtual Void StartEntity(SFXAnsiStringConstRef name);

    virtual Void NotationDecl(SFXAnsiStringConstRef name,
        SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId);
    virtual Void UnparsedEntityDecl(SFXAnsiStringConstRef name,
        SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId,
        SFXAnsiStringConstRef notationName);

    virtual Void ElementDecl(SFXAnsiStringConstRef name,
        SFXAnsiStringConstRef model);
    virtual Void AttributeDecl(SFXAnsiStringConstRef ename,
        SFXAnsiStringConstRef aname, SFXAnsiStringConstRef type,
        SFXAnsiStringConstRef valuedefault, SFXAnsiStringConstRef value);
    virtual Void InternalEntityDecl(SFXAnsiStringConstRef name,
        SFXAnsiStringConstRef value);
    virtual Void ExternalEntityDecl(SFXAnsiStringConstRef name,
        SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId);

    virtual Void ErrorReport(SFCErrorConst error,
        SFXAnsiStringConstRef errInfo);
};
ハンドラ クラスの実装( SFXXMLDefaultHandler クラスを継承するクラス )
// コンストラクタ
MyXMLHandler::MyXMLHandler(Void)
{
    return;
}

// デストラクタ
MyXMLHandler::~MyXMLHandler(Void)
{
    return;
}

// 文書の開始通知を受け取るハンドラ
Void MyXMLHandler::StartDocument(Void)
{
    TRACE("document start");
}

// 文書の終了通知を受け取るハンドラ
Void MyXMLHandler::EndDocument(Void)
{
    TRACE("document end");
}

// 要素の開始通知を受け取るハンドラ
Void MyXMLHandler::StartElement(SFXAnsiStringConstRef uri,
    SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname,
    SFXXMLGrammar::XMLAttrListConstRef attrList)
{
    // 要素名を表示
    TRACE("element: %s start", qname.GetCString());
}

// 要素の終了通知を受け取るハンドラ
Void MyXMLHandler::EndElement(SFXAnsiStringConstRef uri,
    SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname)
{
    TRACE("element: %s end", qname.GetCString());
}

// 文字データの通知を受け取るハンドラ
Void MyXMLHandler::Characters(SFXAnsiStringConstRef string,
    BoolConst /*cdataSection*/)
{
    TRACE("text: %s", string.GetCString());
    return;
}

// ↓以下は空のハンドラ ( イベントを無視する場合も定義する )

Void MyXMLHandler::IgnorableWhitespace(SFXAnsiStringConstRef string)
{
    return;
}

Void MyXMLHandler::ProcessingInstruction(SFXAnsiStringConstRef target,
    SFXAnsiStringConstRef data)
{
    return;
}

Void MyXMLHandler::EndPrefixMapping(SFXAnsiStringConstRef  prefix)
{
    return;
}

Void MyXMLHandler::StartPrefixMapping(SFXAnsiStringConstRef  prefix,
    SFXAnsiStringConstRef uri)
{
    return;
}

Void MyXMLHandler::Comment(SFXAnsiStringConstRef string)
{
    return;
}

Void MyXMLHandler::EndCDATA(Void)
{
    return;
}

Void MyXMLHandler::EndDTD(Void)
{
    return;
}

Void MyXMLHandler::EndEntity(SFXAnsiStringConstRef name)
{
    return;
}

Void MyXMLHandler::StartCDATA(Void)
{
    return;
}

Void MyXMLHandler::StartDTD(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId)
{
    return;
}

Void MyXMLHandler::StartEntity(SFXAnsiStringConstRef name)
{
    return;
}

Void MyXMLHandler::NotationDecl(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId)
{
    return;
}

Void MyXMLHandler::UnparsedEntityDecl(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId,
    SFXAnsiStringConstRef notationName)
{
    return;
}

Void MyXMLHandler::ElementDecl(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef model)
{
    return;
}

Void MyXMLHandler::AttributeDecl(SFXAnsiStringConstRef ename,
    SFXAnsiStringConstRef aname, SFXAnsiStringConstRef type,
    SFXAnsiStringConstRef mode, SFXAnsiStringConstRef value)
{
    return;
}

Void MyXMLHandler::InternalEntityDecl(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef value)
{
    return;
}

Void MyXMLHandler::ExternalEntityDecl(SFXAnsiStringConstRef name,
    SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId)
{
    return;
}

Void MyXMLHandler::ErrorReport(SFCErrorConst error,
    SFXAnsiStringConstRef errInfo)
{
    TRACE("----- ErrorReport ------");
    TRACE("error-%x", error);
    TRACE("errInfo-%s", errInfo.GetCString());
}
      

DOM パーサーを使って XML 文書を解析する

SFXXMLDOMParser::Parse を使って、XML 文書を読み込み、解析します。

解析する文書( file.xml )
<fruit>
  <name>apple</name>
  <size>XS</size>
  <color>red</color>
</fruit>
要素の取得するサンプルコード
SFXXMLDOMParser parser;     // DOM パーサ
SFCError error;             // エラー値
SFXAnsiString resultString; // 結果を格納する文字列

// file.xml に保存した XML 文書を解析する
if ((error = parser.Parse("/file.xml")) == SFERR_NO_ERROR) {
    // ルート要素を取得する
    SFXXMLDocumentPtr root = parser.GetDocument(); 
   // ルート要素の最初の子要素 ( "fruit" 要素 ) を取得する
    SFXXMLNodePtr child = root->GetFirstChild();   

    // "fruit" 要素のすべての子要素を取得する
    // SFXXMLNode::DOMNodeListPtr は SFXList と同じ
    SFXXMLNode::DOMNodeListPtr nodeList = child->GetChildNodes();

    // イテレータを取得する
    SFXXMLNode::DOMNodeList::Iterator itor = nodeList->GetIterator();

    while (itor.HasNext()) { // 次の要素があるかぎり繰り返す

        // "name"要素、"size"要素、"color" 要素の順に取得できる
        SFXXMLNodePtr node = itor.GetNext();

        // 要素の名前を取得する
        resultString = node->GetNodeName();

        // 要素のテキストを取得する 
        // ( "name" の場合は "apple"、"size" の場合は "XS" 、
        // "color"の場合は"red")
        resultString = node->GetText();
    }
}
      

子ノードを置換する

SFXXMLNode::ReplaceChild メソッドを使って、子ノードを置換します。

// "book" 要素を作成する
 SFXXMLElementPtr book = document.CreateElement("book");
// Element ノードを作成する    
SFXXMLElementPtr isbn = document.CreateElement("ISBN");
// Text ノードを作成し、Element ノードに追加する   
isbn->AppendChild(SFXXMLNodePtr(document.CreateTextNode("4-7741-1616-5")));
// 最初の子ノードをその Element ノードに置換する
book->ReplaceChild(SFXXMLNodePtr(isbn), book->GetFirstChild());
      

子孫ノードも含めて子ノードを削除する

SFXXMLNode::RemoveChild を使って子ノードを削除します。

SFXXMLDocumentPtr root = parser.GetDocument();  // ルート ノードを取得する
SFXXMLNodePtr node= root->GetLastChild();   // 最後の子ノードを取得する

root->RemoveChild(node);  // その子ノードを削除する   
      

ノードを挿入する

SFXXMLNode::InsertBefore メソッドを使って、ノードを挿入します。

// "book" 要素を作成する
 SFXXMLElementPtr book = document.CreateElement("book");
// Element ノードを作成する    
SFXXMLElementPtr isbn = document.CreateElement("ISBN");
// Text ノードを作成し、Element ノードに追加する   
isbn->AppendChild(SFXXMLNodePtr(document.CreateTextNode("4-7741-1616-5")));
// Element ノードを挿入する   
book->InsertBefore(SFXXMLNodePtr(isbn), book->GetFirstChild());
      

ノードのテキストを取得する

SFXXMLNode::GetText メソッドを使って、ノードのテキストを取得します。

SFXXMLDocumentPtr root = parser.GetDocument(); // ルート ノードを取得する

SFXXMLNodePtr child = root->GetFirstChild();   // 最初の子ノードを取得する

// ノードのテキストを取得し、表示する
TRACE("%s", child->GetText().GetCString());
      

前の兄弟ノードを取得する

SFXXMLNode::GetPreviousSibling メソッドを使って、前の兄弟ノードを取得します。

SFXXMLDocumentPtr root = parser.GetDocument();  // ルート ノードを取得する
SFXXMLNodePtr node= root->GetLastChild();   // 最後の子ノードを取得する

// 前の兄弟ノードを取得する
SFXXMLNodePtr date = node->GetPreviousSibling();
      

親ノードを取得する

SFXXMLNode::GetNodeValue メソッドを使って、親ノードを取得します。

SFXXMLDocumentPtr root = parser.GetDocument();  //ルート ノードを取得する
SFXXMLNodePtr node= root->GetFirstChild();   // 最初の子ノードを取得する

// 何か処理を行う
...

SFXXMLNodePtr boot = node->GetParentNode();  // 親ノードを取得する
      

ノードの値を取得する

SFXXMLNode::GetNodeValue メソッドを使って、ノードの値を取得します。

SFXXMLDocumentPtr root = parser.GetDocument();   //ルート ノードを取得する
SFXXMLNodePtr collection = root->GetFirstChild();   // 最初の子ノードを取得する

 // Element ノードのポインターに変換する
SFXXMLElementPtr elem = static_cast(collection); 
// Element ノードの 最初の子ノードを取得する
SFXXMLNodePtr node = elem->GetFirstChild();          

// ノードが Comment ノードなら
if (node->GetNodeType() == SFXXMLNode::COMMENT_NODE) {
     // ノードの内容を表示する
    TRACE("comment value: %s", node->GetNodeValue());   
}
      

ノード名を取得する

SFXXMLNode::GetNodeName メソッドを使って、ノード名を取得します。

SFXXMLDOMParser parser;    // DOM パーサ 

SFXXMLDocumentPtr root = parser.GetDocument();  // ルート ノードを取得する

SFXXMLNodePtr node = root->GetFirstChild();  // 最初の子ノードを取得する  

TRACE("node name: %s", node->GetNodeName());  // ノード名を取得を表示する  
      

指定したノードの次の兄弟ノードを取得する

SFXXMLNode::GetNextSibling メソッドを使って、次の兄弟ノードを取得します。

SFXXMLDOMParser parser;    // DOM パーサ 

SFXXMLDocumentPtr root = parser.GetDocument();  // ルート ノードを取得する

SFXXMLNodePtr node = root->GetFirstChild();      // 最初の子ノードを取得する
SFXXMLNodePtr node2 = root->GetNextSibling();    // 次の兄弟ノードを取得する
      

最後の子ノードを取得する

SFXXMLNode::GetLastChild メソッドを利用して、最後の子ノードを取得します。

SFXXMLDOMParser parser; // DOM パーサ
    
SFXXMLDocumentPtr root = parser.GetDocument();   // ルート ノードを取得する
SFXXMLNodePtr child = root->GetLastChild();   // 最後の子ノードを取得する
      

最初の子ノードを取得する

SFXXMLNode::GetFirstChild メソッドを使用して、最初の子ノードを取得します。

SFXXMLDOMParser parser;    // DOM パーサ 

SFXXMLDocumentPtr root = parser.GetDocument();   // ルート ノードを取得する
SFXXMLNodePtr node = root->GetFirstChild();    // 最初の子ノードを取得する
      

すべての子ノードを取得する

SFXXMLNode::GetChildNodes メソッドを使用して、すべての子ノードを取得します。

// タグ名が "BOOK" である、すべての Element ノードを取得する
SFXXMLNode::DOMNodeListPtr list = root->GetElementsByTagName("BOOK");

 if (list) {
    // 列挙子を取得する
    SFXXMLNode::DOMNodeList::Enumerator enumer = list->GetFirstEnumerator();

    while (enumer.HasNext()) {
        // 各  Element ノードを取得する
        SFXXMLElementPtr elem = static_cast(enumer.GetNext());
        //  Element ノードのすべての子ノードを取得する
        SFXXMLNode::DOMNodeListPtr nodeList = elem->GetChildNodes();
        // 子要素の列挙子を取得する
        SFXXMLNode::DOMNodeList::Enumerator childiter = 
                                               nodeList->GetFirstEnumerator();

        while (childiter.HasNext()) {
            SFXXMLElementPtr child = static_cast(childiter.GetNext());

      // 子ノードの名前を表示する
            TRACE("child name: %s", child->GetName());    
             // 子ノードの内容を表示する
            TRACE("child text: %s", child->GetText().GetCString()); 
        }
    }
}
      

RPC による Web サービス呼び出し方法

SFXSOAPRPC::Invoke() メソッドを使用して Web サービスを呼び出します。

// Amazon の ID を設定する
#define AMAZON_ID  "" 
                            
SFMTYPEDEFCLASS(SOAPTest)
class SOAPTest : public SFCApplication {
    SFMSEALCOPY(SOAPTest)
private:
    // SOAP RPC プロトコルを扱う変数
    SFXSOAPRPC _rpc;    

    Void OnSOAP(Void);
    static Void OnResultSHP_SOAP(SFCError error, 
                                 const SFXSOAPRPC::Params& result, 
                                 const SFXSOAPRPC::FAULT& fault, 
                                 SFXSOAPParserConstRef soap, 
                                 VoidPtr reference);
    Void OnResult_SOAP(SFCError error, 
                       const SFXSOAPRPC::Params& result, 
                       const SFXSOAPRPC::FAULT& fault, 
                       SFXSOAPParserConstRef soap);
};

Void SOAPTest::OnSOAP(Void)
{
    // メソッド名を設定する
    _rpc.SetMethodName("ItemSearch");

    // ターゲットとなるURIを設定する
    _rpc.SetTargetObjectURI("https://webservices.amazon.com/");

    // Web サービスのパラメーターを設定する
    _rpc.AddParameter("AWSAccessKeyId", 
                      SFXBuffer(SFXAnsiString(AMAZON_ID)));
    _rpc.AddParameter("Keywords", 
                      SFXBuffer(SFXAnsiString("caviar")));
    _rpc.AddParameter("MerchantId", 
                      SFXBuffer(SFXAnsiString("Amazon")));
    _rpc.AddParameter("SearchIndex", 
                      SFXBuffer(SFXAnsiString("GourmetFood")));

    // SSL の検証モードを設定する
    _rpc.SetTrustMode(SSL_TRUST_MODE_IGNORE);

    // Web サービスを呼び出す
    _rpc.Invoke("https://soap.amazon.com/onca/soap?Service=AWSECommerceService",
                "https://soap.amazon.com",
                OnResultSHP_SOAP,
                this);
}

// コールバック関数
// error : エラー値 
// result : SOAP の戻り値 
// fault : SOAP 文書中でエラーである Fault 要素の内容 
// soap : SOAP 文書のリファレンス 
// reference : コールバック関数に渡されるデータ
Void SOAPTest::OnResultSHP_SOAP(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap, VoidPtr reference)
{
    static_cast(reference)->OnResult_SOAP(error, result, fault, soap);
}

// SOAP 文書を処理する関数
Void SOAPTest::OnResult_SOAP(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap)
{
    if (error == SFERR_NO_ERROR) {

        // SFXSOAPRPC::Params で各要素値を取得する
        // Params 配列は SOAP 文書に出てくる要素の順に保存する

        // 列挙子を取得する
        SFXSOAPRPC::Params::Enumerator para = result.GetFirstEnumerator();

        while (para.HasNext()) {

            // 各要素を取得する
            SFXSOAPRPC::LPPARAMETER temp = para.GetNext();

            // パラメーターの名前を取得し、表示する
            TRACE("parameter-name: %s", temp->_name.GetCString());
            // パラメーターのタイプを取得し、表示する
            TRACE("parameter-type: %d", temp->_type);

            if (!temp->_value.IsEmpty()) {
                // パラメーターの値を取得し、表示する
                TRACE("parameter-value: %s", 
                      ACharConstPtr(temp->_value.GetBuffer()));
            }
        }
   }
   // サーバーから、エラー メッセージを取得する
   else if (error == SFERR_SOAP_FAULT_MESSAGE) {

        // faultactor 要素が空でない場合
        if(!fault._faultactor.IsEmpty())
            // faultactor 要素を表示する
            TRACE("faultactor: %s", fault._faultactor.GetCString());    

        // faultcode 要素が空でない場合
        if(!fault._faultcode.IsEmpty())
            // faultcode 要素を表示する
            TRACE("faultcode: %s", fault._faultcode.GetCString());      

        // faultstring 要素が空でない場合
        if(!fault._faultstring.IsEmpty())
            // faultstring 要素を表示を表示する
            TRACE("faultstring: %s", fault._faultstring.GetCString());  

        // detail 要素が空でない場合
        if (fault._faultdetail) 
            // detail 要素を表示を表示する
            TRACE("faultstring: %s", fault._faultdetail->GetText().GetCString());  
    }
    return;
}
      

Webサービスのメソッド呼び出しにstring型以外の型を使う

Webサービスに関する 2 つのクラス( SFXSOAPRPCSFXSOAPServiceProxy )では、24種類のパラメータタイプがサポートされています。

SFXSOAPRPC rpc;

// int 型のパラメータを指定する
rpc.AddParameter("Index", SFXBuffer(SFXAnsiString("1")),
    SFXSOAPRPC::PARAMETER::SOAP_INT, SFXSOAPRPC::PARAMETER::IN );

※1. 値はSFXBufferオブジェクトに保存し、パラメータのタイプと入出モードを指定します。

※2. タイプのデフォルト値はPARAMETER::XSD_STRING、入出力モードのデフォルト値は PARAMETER::IN です。

参照 SFXSOAPRPC::AddParameter | SFXSOAPRPC::PARAMETER::SOAP_INT