SophiaFramework UNIVERSE 5.3 |
例 19.2. 解析対象の XML 文書 ( file.xml )
<fruit> <name>apple</name> <size>XS</size> <color>red</color> </fruit>
例 19.3. 要素の取得
SFCError error; // エラー値 SFXXMLDOMParser parser; // DOM パーサー SFXAnsiString resultString; // ノードの名前を格納する変数 // file.xml に保存した XML 文書を解析する if ((error = parser.Parse(SFXPath("/file.xml"))) == SFERR_NO_ERROR) { // DOM ツリーのルートノードを取得する SFXXMLDocumentPtr root = parser.GetDocument(); // ルートノードの最初の子ノードを取得する: "fruit" ノード SFXXMLNodePtr child = root->GetFirstChild(); // "fruit" ノードの名前を取得する: "fruit" resultString = child->GetNodeName(); // "fruit" ノードのノードタイプを取得する: ELEMENT_NODE SFXXMLNode::NodeType type = child->GetNodeType(); // "fruit" ノードの最初の子ノードを取得する: "name" ノード SFXXMLNodePtr node = child->GetFirstChild(); // ノードの名前を取得する: "name" resultString = node->GetNodeName(); // ノードタイプを取得する: ELEMENT_NODE type = node->GetNodeType(); // "name" ノードの最初の子ノードを取得する: "apple" ノード SFXXMLNodePtr textNode = node->GetFirstChild(); // ノードの値を取得する: "apple" resultString = textNode->GetNodeValue(); // ノードタイプを取得する: TEXT_NODE type = textNode->GetNodeType(); // "name" ノードの、次の兄弟ノードを取得する: "size" ノード node = node->GetNextSibling(); // ノードの名前を取得する: "size" resultString = node->GetNodeName(); // ノードタイプを取得する: ELEMENT_NODE type = node->GetNodeType(); }
注意 | |
---|---|
ルートノードは、SFXXMLDOMParser::GetDocument 関数、 子ノードは SFXXMLNode::GetFirstChild 関数を使用して取得します。 |
例 19.4. 複数ノードの取得
SFCError error; // エラー値 SFXXMLDOMParser parser; // DOM パーサー SFXAnsiString resultString; // ノードの名前を格納する変数 // file.xml に保存した XML 文書を解析する if ((error = parser.Parse(SFXPath("/file.xml"))) == SFERR_NO_ERROR) { // DOM ツリーのルートノードを取得する SFXXMLDocumentPtr root = parser.GetDocument(); // ルートノードの最初の子ノード ( "fruit" ノード ) を取得する SFXXMLNodePtr child = root->GetFirstChild(); // "fruit" ノードのすべての子ノードを取得する // SFXXMLNode::DOMNodeListPtr は SFXList<SFXXMLNodePtr> と同じ SFXXMLNode::DOMNodeListPtr nodeList = child->GetChildNodes(); // イテレータを取得する SFXXMLNode::DOMNodeList::Iterator itor = nodeList->GetFirstIterator(); while (itor.HasNext()) { // 次のノードがあるかぎり繰り返す // "name" ノード、"size" ノード、"color" ノードの順に取得できる SFXXMLNodePtr node = itor.GetNext(); // ノードの名前を取得する resultString = node->GetNodeName(); // ノードのテキストを取得する ( "name" ノードの場合は "apple"、"size" ノードの場合は "XS" ) resultString = node->GetText(); } // "color" というタグ名を持つすべての Element ノードを取得する nodeList = static_cast<SFXXMLElementPtr>(child)->GetElementsByTagName("color"); // イテレータを取得する itor = nodeList->GetFirstIterator(); // 各 Element ノードに対する処理 while (itor.HasNext()) { // 次の Element ノードを取得する SFXXMLNodePtr node = itor.GetNext(); // ... } }
注意 | |
---|---|
すべての子ノードを取得するには、 SFXXMLNode::GetChildNodes 関数を呼び出します。 |
例 19.5. 解析対象の 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>
例 19.6. 各ノードに対する処理
SFCError error; // エラー値 SFXXMLDOMParser parser; // DOM パーサー // file.xml に保存した XML 文書を解析する if ((error = parser.Parse(SFXPath("/file.xml"))) == SFERR_NO_ERROR) { // DOM ツリーのルートノードを取得する SFXXMLDocumentPtr root = parser.GetDocument(); // ルートノードの最初の子ノード ( "fruits" ノード ) を取得する SFXXMLNodePtr child = root->GetFirstChild(); // "fruits" ノードの最初の子ノード( "fruit" ノード)を取得する SFXXMLNodePtr node = child->GetFirstChild(); // "fruit" ノードの各子ノードに対する処理 while (node != null) { // 最初の子ノード( "name" ノード)を取得する SFXXMLNodePtr nameNode = node->GetFirstChild(); // ノードのテキストを取得する SFXAnsiString resultString = nameNode->GetText(); // 次の兄弟ノードを取得する node = node->GetNextSibling(); } }
注意 | |
---|---|
兄弟ノードは while ループ内で SFXXMLNode::GetNextSibling 関数を呼び出して順次取得します。 |
例 19.7. 解析対象の XML 文書 ( file.xml )
<fruit> <name language="english" code="ascii">apple</name> <size>XS</size> <color>red</color> </fruit>
例 19.8. 属性の取得
SFCError error; // エラー値 SFXXMLDOMParser parser; // DOM パーサー SFXAnsiString resultString; // 属性の値を格納する変数 // file.xml に保存した XML 文書を解析する if ((error = parser.Parse(SFXPath("/file.xml"))) == SFERR_NO_ERROR) { // DOM ツリーのルートノードを取得する SFXXMLDocumentPtr root = parser.GetDocument(); // ルートノードの最初の子ノード ( "fruit" ノード ) を取得する SFXXMLNodePtr child = root->GetFirstChild(); // "fruit" ノードの最初の子ノード ( "name" ノード ) を取得する child = child->GetFirstChild(); // child ノードの名前が "name" のとき if (SFXAnsiString("name").Equals(child->GetNodeName())) { // Attribute ノードは Element ノードから取得するので、キャストの必要がある SFXXMLElementPtr element = static_cast<SFXXMLElementPtr>(child); // "language" という名前の Attribute ノードの値を取得する // resultString は "english" になる resultString = element->GetAttribute("language"); // "language" という名前の Attribute ノード を取得する SFXXMLAttributePtr attr = element->GetAttributeNode("language"); // Attribute ノードの値(属性値)を取得する: "english" resultString = attr->GetNodeValue(); // すべての Attribute ノード を取得する SFXXMLNode::DOMNamedNodeMapPtr nodeMap = element->GetAttributes(); // DOMNamedNodeMap から名前を指定して Attribute ノード を取得する attr = static_cast<SFXXMLAttributePtr>(nodeMap->GetNamedItem("code")); // Attribute ノードの値(属性値)を取得する: "ascii" resultString = attr->GetNodeValue(); } }
注意 | |
---|---|
Element ノードの属性値を取得するには、 属性名を指定して SFXXMLElement::GetAttribute 関数を呼び出します。 Element ノードの Attribute ノードを取得するには、 属性名を指定して SFXXMLElement::GetAttributeNode 関数を呼び出します。 Element ノードに含まれるすべての Attribute ノードを取得するには、 SFXXMLElement::GetAttributes 関数を呼び出します。 |
XML 文書の作成
XML 文書は SFXXMLDocument クラスや SFXXMLElement クラスを使用して以下の手順で作成します。
例 19.9. XML 文書の作成
SFCError error; // エラー値 // document ノード(Document ノード: DOM ツリーのルートノード)を作成する SFXXMLDocument document; // document ノードに XML 文書のバージョンを設定する document.SetVersion("1.0"); // collection ノード(タグ名が "COLLECTION" の Element ノード)を作成する SFXXMLElementPtr collection = document.CreateElement("COLLECTION"); if (collection == null) { return SFERR_NO_MEMORY; } // document ノードに collection ノードを追加する if ((error = document.AppendChild(SFXXMLNodePtr(collection))) != SFERR_NO_ERROR) { return error; } // collection ノードに属性を追加する collection->SetAttribute("xmlns:dt", "urn:schemas-microsoft-com:datatypes"); // date ノード(タグ名が "DATE" の Element ノード)を作成する SFXXMLElementPtr date = document.CreateElement("DATE"); if (date == null) { return SFERR_NO_MEMORY; } // date ノードに属性を追加する date->SetAttribute("dt:dt", "datetime"); // date ノードにテキスト情報を追加する if ((error = date->AppendChild(SFXXMLNodePtr(document.CreateTextNode("1998-10-13T15:56:00")))) != SFERR_NO_ERROR) { return error; } // collection ノードに date ノードを追加する if ((error = collection->AppendChild(SFXXMLNodePtr(date))) != SFERR_NO_ERROR) { return error; } // book ノード(タグ名が "BOOK" の Element ノード)を作成する SFXXMLElementPtr book = document.CreateElement("BOOK"); if (book == null) { return SFERR_NO_MEMORY; } // collection ノードに book ノードを追加する if ((error = collection->AppendChild(SFXXMLNodePtr(book))) != SFERR_NO_ERROR) { return error; } // "<TITLE>Cosmos</TITLE>" を作成する SFXXMLElementPtr title = document.CreateElement("TITLE"); if (title == null) { return SFERR_NO_MEMORY; } if ((error = title->AppendChild(SFXXMLNodePtr(document.CreateTextNode("Cosmos")))) != SFERR_NO_ERROR) { return error; } if ((error = book->AppendChild(SFXXMLNodePtr(title))) != SFERR_NO_ERROR) { return error; } // "<AUTHOR>Carl Sagan</AUTHOR>" を作成する SFXXMLElementPtr author = document.CreateElement("AUTHOR"); if (author == null) { return SFERR_NO_MEMORY; } if ((error = author->AppendChild(SFXXMLNodePtr(document.CreateTextNode("Carl Sagan")))) != SFERR_NO_ERROR) { return error; } if ((error = book->AppendChild(SFXXMLNodePtr(author))) != SFERR_NO_ERROR) { return error; } // "<PUBLISHER>Ballantine Books</PUBLISHER>" を作成する SFXXMLElementPtr publisher = document.CreateElement("PUBLISHER"); if (publisher == null) { return SFERR_NO_MEMORY; } if ((error = publisher->AppendChild(SFXXMLNodePtr(document.CreateTextNode("Ballantine Books")))) != SFERR_NO_ERROR) { return error; } if ((error = book->AppendChild(SFXXMLNodePtr(publisher))) != SFERR_NO_ERROR) { return error; } // XML 文書を保存する if ((error = document.Save("book.xml")) != SFERR_NO_ERROR) { return error; }
例 19.10. 実行結果
<?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>
エミュレーター使用時の注意 | |
---|---|
エミュレーターのファイルシステムの容量がオーバーした場合は、"book.xml" は生成されません。 |
SAX パーサー(SFXXMLSAXParser)は、 イベント駆動型の XML パーサーです。
SAX パーサーによる XML 文書解析では、 XML 文書を先頭から解析していき、 タグや属性が現れるたびにイベントが発生します。
そして発生したイベントの種類に応じて、 開発者は SFXXMLDefaultHandler クラスを継承して定義したハンドラクラスのハンドラ関数が呼び出されます。
このハンドラクラスは、 XML 文書を解析する前に SFXXMLSAXParser::SetDefaultHandler 関数を使用して SAX パーサーに登録する必要があります。
例 19.11. 解析対象の XML 文書 ( file.xml )
<fruit> <name language="english" code="ascii">apple</name> <size>XS</size> <color>red</color> </fruit>
例 19.12. ハンドラクラスの定義と実装
// ハンドラクラス class MyXMLHandler : public SFXXMLDefaultHandler { public: explicit MyXMLHandler(Void); virtual ~MyXMLHandler(Void); // 各ハンドラの宣言 // XML 文書の始まりと終わりを通知を取得するハンドラ virtual Void StartDocument(Void); virtual Void EndDocument(Void); // DTD の通知を取得するハンドラ virtual Void StartDTD(SFXAnsiStringConstRef name, SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId); virtual Void EndDTD(Void); virtual Void StartEntity(SFXAnsiStringConstRef name); virtual Void EndEntity(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); // XML インスタンス(XML 文書のデータの内容)の通知を取得するハンドラ virtual Void StartElement(SFXAnsiStringConstRef uri,SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname, SFXXMLGrammar::XMLAttrListConstRef attrList); virtual Void EndElement(SFXAnsiStringConstRef uri = SFXAnsiString::EmptyInstance(), SFXAnsiStringConstRef localname = SFXAnsiString::EmptyInstance(), SFXAnsiStringConstRef qname = SFXAnsiString::EmptyInstance()); virtual Void StartPrefixMapping(SFXAnsiStringConstRef prefix, SFXAnsiStringConstRef uri); virtual Void EndPrefixMapping(SFXAnsiStringConstRef prefix); virtual Void Characters(SFXAnsiStringConstRef string, BoolConst cdataSection = true); virtual Void IgnorableWhitespace(SFXAnsiStringConstRef string); virtual Void ProcessingInstruction(SFXAnsiStringConstRef target, SFXAnsiStringConstRef data); virtual Void Comment(SFXAnsiStringConstRef string); virtual Void StartCDATA(Void); virtual Void EndCDATA(Void); // エラーの通知を取得するハンドラ virtual Void ErrorReport(SFCErrorConst error, SFXAnsiStringConstRef errInfo); }; // コンストラクタ 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()); // 要素の最初の属性対応する列挙子を取得する SFXXMLGrammar::XMLAttrList::Enumerator etor = attrList.GetFirstEnumerator(); // すべての属性の名前と値を表示する while (etor.HasNext()) { SFXXMLGrammar::LPXMLATTR attr = etor.GetNext(); // 次の属性を取得する TRACE("attrname: %s", attr->_attName.GetCString()); // 属性の名前を表示する TRACE("attrvalue: %s", attr->_value.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::Comment(SFXAnsiStringConstRef string) { return; } // CDATA セクションの開始通知を受け取るハンドラ Void MyXMLHandler::StartCDATA(Void) { return; } // CDATA セクションの終了通知を受け取るハンドラ Void MyXMLHandler::EndCDATA(Void) { return; } // 処理命令の通知を受け取るハンドラ Void MyXMLHandler::ProcessingInstruction(SFXAnsiStringConstRef target, SFXAnsiStringConstRef data) { return; } // 名前空間接頭辞と URI 名前空間マッピングのスコープの開始通知を受け取るハンドラ Void MyXMLHandler::StartPrefixMapping(SFXAnsiStringConstRef prefix, SFXAnsiStringConstRef uri) { return; } // 名前空間接頭辞と URI 名前空間マッピングのスコープの終了通知を受け取るハンドラ Void MyXMLHandler::EndPrefixMapping(SFXAnsiStringConstRef prefix) { return; } // DTD 宣言の開始通知を受け取るハンドラ Void MyXMLHandler::StartDTD(SFXAnsiStringConstRef name, SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId) { return; } // DTD 宣言の終了通知を受け取るハンドラ Void MyXMLHandler::EndDTD(Void) { return; } // エンティティの開始通知を受け取るハンドラ Void MyXMLHandler::StartEntity(SFXAnsiStringConstRef name) { return; } // エンティティの終了通知を受け取るハンドラ Void MyXMLHandler::EndEntity(SFXAnsiStringConstRef name) { return; } // 要素型宣言の通知を受け取るハンドラ Void MyXMLHandler::ElementDecl(SFXAnsiStringConstRef name, SFXAnsiStringConstRef model) { return; } // ATTLIST 宣言の通知を受け取るハンドラ Void MyXMLHandler::AttributeDecl(SFXAnsiStringConstRef ename, SFXAnsiStringConstRef aname, SFXAnsiStringConstRef type, SFXAnsiStringConstRef mode, SFXAnsiStringConstRef value) { 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::InternalEntityDecl(SFXAnsiStringConstRef name, SFXAnsiStringConstRef value) { return; } // 外部エンティティ宣言の通知を受け取るハンドラ Void MyXMLHandler::ExternalEntityDecl(SFXAnsiStringConstRef name, SFXAnsiStringConstRef publicId, SFXAnsiStringConstRef systemId) { return; } // エラーの通知を受け取るハンドラ Void MyXMLHandler::ErrorReport(SFCErrorConst error, SFXAnsiStringConstRef errInfo) { return; }
例 19.13. SAX パーサーの使い方
SFCError error; // エラー値 SFXXMLSAXParser parser; // SAX パーサー MyXMLHandler handler; // イベントハンドラ // ハンドラを設定する parser.SetDefaultHandler(&handler); // XML 文書を解析する error = parser.Parse(SFXPath("/file.xml"));
例 19.14. 実行結果
document start element: fruit start element: name start attrname: language attrvalue: english attrname: code attrvalue: ascii text: apple element: name end element: size start text: XS element: size end element: color start text: red element: color end element: fruit end document end parse end
次に、各要素を SFXProperty クラスのインスタンスに格納します。
例 19.15. 解析対象の XML 文書 ( file.xml )
<fruits> <fruit> <name>apple</name> <size>XS</size> <color>red</color> </fruit> <fruit> <name>grape</name> <size>SS</size> <color>purple</color> </fruit> <fruit> <name>peach</name> <size>M</size> <color>pink</color> </fruit> <fruit> <name>pineapple</name> <size>LL</size> <color>yellow</color> </fruit> </fruits>
例 19.16. ハンドラ クラスの定義と実装
// ハンドラ クラス class MyXMLHandler : public SFXXMLDefaultHandler { private: // 要素のペアを格納するクラス SFXProperty _property; // name タグの中身を一時保存する SFXAnsiString _name; // size タグの中身を一時保存する SFXAnsiString _size; // タグの種類 enum KindOfTag {NOTHING, NAME, SIZE, COLOR}; // 現在解析しているタグの種類 KindOfTag _kind; public: // 以後の処理は SAX パーサー ハンドラ クラスの定義と同じ }; // コンストラクタ MyXMLHandler::MyXMLHandler(Void) { _kind = NOTHING; return; } // 要素の開始通知を受け取るハンドラ Void MyXMLHandler::StartElement(SFXAnsiStringConstRef uri, SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname, SFXXMLGrammar::XMLAttrListConstRef attrList) { if (qname.Equals("name")) { // タグの名前が name のとき _kind = NAME; // name タグを解析中であることを表す } else if (qname.Equals("size")) { _kind = SIZE; } else if (qname.Equals("color")) { _kind = COLOR; } return; } // 要素の終了通知を受け取るハンドラ Void MyXMLHandler::EndElement(SFXAnsiStringConstRef uri, SFXAnsiStringConstRef localname, SFXAnsiStringConstRef qname) { if (qname.Equals("fruit")) { // fruit タグの終わりのとき // _name, _size に保存しておいたテキストを格納する _property.Append(_name, _size); } _kind = NOTHING; return; } // 文字データの通知を受け取るハンドラ Void MyXMLHandler::Characters(SFXAnsiStringConstRef string, BoolConst /*cdataSection*/) { switch (_kind) { case NAME: // name を解析中のとき _name = string; // テキストを _name に格納する break; case SIZE: _size = string; break; default: break; } return; }
XML 文書の各 name 要素と size 要素のテキストをペアにして SFXProperty インスタンスに格納します。
例 19.17. 解析対象の XML 文書 ( file.xml )
<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE Mail SYSTEM "personal.dtd"> <Mail> <From>&name;</From> <To>Receiver</To> <Cc>&Email;</Cc> <Date> Thu, 7 Oct 1999 11:15:16 -0600</Date> <Subject>XML Introduction</Subject> <Body>Comments:<P align = "right">Thanks for reading<br/>this article</P> <br/> <P>Hope you enjoyed this article</P> <P>©right;</P> </Body> </Mail>
例 19.18. 検証用の DTD ファイル ( personal.dtd )
<?xml encoding="ISO-8859-1"?> <!-- @version: 10.1--> <!ELEMENT Mail (From, To, Cc?, Date?, Subject, Body)> <!ELEMENT From (#PCDATA)> <!ELEMENT To (#PCDATA)> <!ELEMENT Cc (#PCDATA)> <!ELEMENT Date (#PCDATA)> <!ELEMENT Subject (#PCDATA)> <!ELEMENT Body (#PCDATA | P | Br)*> <!ELEMENT P (#PCDATA | br)*> <!ATTLIST P align (left | right | justify) "left"> <!ELEMENT br EMPTY> <!ENTITY name "sophia"> <!ENTITY Email "&name;@s-cradle.com"> <!ENTITY copyright "Copyright (C) 2005 - 2006 Sophia Cradle Incorporated.">
例 19.19. DTD 付き XML 文書の解析
SFXXMLDOMParser parser; SFCError error; // DTD 付きの XML 文書を解析するため、文法タイプを設定する parser.SetGrammar(SFXXMLGrammar::GRAMMAR_DTD); // XML 文書を DTD で検証するように設定する parser.SetValidationDTD(true); // 外部 DTD を読み込むように設定する parser.SetLoadExternalDTD(true); // XML 文書を解析する error = parser.Parse(SFXPath("/file.xml")); if (error == SFERR_NO_ERROR) { // ルートノードを取得する SFXXMLDocumentPtr root = parser.GetDocument(); // ドキュメント型を取得する SFXXMLDocumentTypePtr documentType = root->GetDocumentType(); // 外部サブセット ( external DTD subset ) のシステム識別子を取得する // id は "personal.dtd" になる SFXAnsiString id = documentType->GetSystemID(); // DTD に定義されているエンティティを DOMNamedNodeMap として取得する SFXXMLNode::DOMNamedNodeMapPtr entitymap = documentType->GetEntities(); // "name" エンティティの値を取得する // name は "sophia" になる SFXAnsiString name = SFXXMLEntityPtr(entitymap-> GetNamedItem("name"))->GetValue(); }
例 19.20. スキーマ付き XML 文書の解析サンプルコード
SFXXMLDOMParser parser; // コメント 要素を作成するように設定する parser.SetCreateCommentNodes(true); // 名前空間を処理するように設定する parser.SetDoNamespaces(true); // Schema 付きの XML 文書を解析するため、文法タイプを設定する parser.SetGrammar(SFXXMLGrammar::GRAMMAR_SCHEMA); // スキーマを処理するように設定する parser.SetDoSchema(true); // スキーマ付き XML 文書の XSD ファイルを指定する // デフォルト フォルダはアプリのホームフォルダになる parser.SetSchemaLocation("schema.xsd"); // XML 文書をスキーマで検証するように設定する parser.SetValidationSchema(true); // XML Schema に "annotation" 定義した要素を無視するように設定する parser.SetIgnoreAnnotations(false); // XML 文書を解析する error = parser.Parse(SFXPath("/file.xml"));
例 19.21. SOAP メッセージの作成
SFXSOAPWriter soapwriter; // SOAP メッセージの各要素を生成するオブジェクト SFCError error; // エラー値を保存する変数 // Envelope 要素を作成する // 名前空間接頭辞: デフォルトは "SOAP-ENV" // SOAP バージョン: SFXSOAPParser::SOAP_VERSION_1_2 の場合、"http://www.w3.org/2003/05/soap-envelope" // SFXSOAPParser::SOAP_VERSION_1_1 の場合、"http://schemas.xmlsoap.org/soap/envelope/" // SOAP エンコーディング: "STANDARD" の場合、"http://schemas.xmlsoap.org/soap/encoding/" // "NONE" の場合、SOAP エンコーディングは何も指定しない 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); } // faultcode、faultstring、および faultactor 要素から構成される SOAP Fault 要素を設定する(デフォルトでは Body 要素の子要素となる) soapwriter.SetFault("testing-fault-code","testing-fault-string","testing-fault-actor"); // SOAP Fault 要素に detail 要素を設定する 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); } }
例 19.22. 実行結果
<?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>
表 19.21. SOAP エラーメッセージ
値 | 解説 |
---|---|
SFERR_SOAP_EXPECT_ENVELOPE(0x699F) | SOAP メッセージに Envelope 要素(SOAP Envelope)がありません。 |
SFERR_SOAP_EXPECT_BODY(0x69A0) | SOAP メッセージに Body 要素(SOAP Body)がありません。 |
SFERR_SOAP_EXPECT_FAULT(0x69A1) | SOAP メッセージに Fault 要素(SOAP Fault)がありません。 |
SFERR_SOAP_REPEATED_ENVELOPE(0x69A2) | SOAP メッセージの Envelope 要素(SOAP Envelope)が重複しています。 |
SFERR_SOAP_REDUNDANT_ELEMENT(0x69A3) | SOAP メッセージに無効な要素があります。 |
SFERR_SOAP_UNSUPPORT_VERSION(0x69A4) | 指定された SOAP のバージョンはサポートされません。 |
SFERR_SOAP_FAULT_MESSAGE(0x69A5) | SOAP メッセージに Fault 要素(SOAP Fault)が含まれます。 |
EFSFULL(0x0106) | ファイルシステムに空き容量がありません。 |
XML エラーメッセージ | |
---|---|
参照: SFCErrorEnum |
例 19.23. SOAP-RPC による Web サービス呼び出し
SFMTYPEDEFCLASS(xmlexplainer) class xmlexplainer : public SFCApplication { SFMSEALCOPY(xmlexplainer) private: // SFXSOAPRPC オブジェクトはクラス変数にする SFXSOAPRPC _rpc; public: static SFCInvokerPtr Factory(Void); private: explicit xmlexplainer(Void) static_throws; virtual ~xmlexplainer(Void); virtual Bool HandleEvent(SFXEventConstRef event); virtual Bool HandleRender(SFXEventConstRef event); Void _SFXSOAPRPC(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 xmlexplainer::_SFXSOAPServiceProxy(Void) { // www.s-cradle.com の "Arithmetic" サービスにアクセスするコード: // ※ 組み込み向けシステムの場合、メモリの制約から、WSDL ファイルのサイズは小さい方が望ましい // SFXSOAPServiceProxy クラスが自動生成する SOAP-RPC リクエストメッセージの内容: 2.0 と 3.0 の和を求める // <?xml version="1.0" encoding="UTF-8"?> // <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> // <SOAP-ENV:Body> // <Add xmlns="http://soapsample.s-cradle.com"> // <left>2.0</left> // <right>3.0</right> // </Add> // </SOAP-ENV:Body> // </SOAP-ENV:Envelope> // 呼び出す Web サービスの機能 (メソッド) を設定する // ※ この場合、足し算の結果を求める _rpc.SetMethodName("Add"); // 指定されたパラメータの値を設定する _rpc.AddParameter("left", SFXBuffer(SFXAnsiString("2.0"))); _rpc.AddParameter("right", SFXBuffer(SFXAnsiString("3.0"))); // Web サービスを呼び出す: 同時に、サーバから返答を受け取るためのコールバック関数(エントリ)を設定する // ※ コールバック関数は静的関数でなければいけないので、一旦 OnResultSHP_SOAP 静的関数を呼び出し、 // OnResultSHP_SOAP() 内からコールバック関数の本体である OnResult_SOAP メンバ関数を呼び出す _rpc.Invoke("/soapsample/Arithmetic", "urn:Add", OnResultSHP_SOAP, this); } return; } // サーバから返答を受け取るためのコールバック関数(エントリ) Void xmlexplainer::OnResultSHP_SOAP(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap, VoidPtr reference) { // サーバから返答を受け取るためのコールバック関数(実体)を呼び出す static_cast<xmlexplainerPtr>(reference)->OnResult_SOAP(error, result, fault, soap); } // サーバから返答を受け取るためのコールバック関数(実体) Void xmlexplainer::OnResult_SOAP(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap) { // サーバから受け取った SOAP-RPC リクエストメッセージの内容は以下の通り: 結果の 5.0 が返却される // <?xml version="1.0" encoding="utf-8"?> // <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> // <soapenv:Body> // <ns:AddResponse xmlns:ns="http://soapsample.s_cradle.com"> // <ns:return>5.0</ns:return> // </ns:AddResponse> // </soapenv:Body> // </soapenv:Envelope> // SOAP-RPC 通信が成功したか判断する if (error == SFERR_NO_ERROR) { // 方法 1: result 引数の値(SFXSOAPRPC::Params 配列)から各要素の値を取得する // ※ SOAP-RPC の結果は SFXSOAPRPC::Params 配列に格納されている // SFXSOAPRPC::Params 配列の列挙子を取得する 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())); } } // 方法 2: SFXSOAPServiceProxy::GetResultValueByName 関数で特定のパラメータを取得する // 指定した名前を持つメソッドレスポンス(SFXSOAPRPC::PARAMETER 構造体)を取得する SFXSOAPRPC::LPPARAMETER result = _wsdl.GetResultValueByName("return"); if (result) { // パラメータの名前を取得し表示する パラメータの名前は "return" になる TRACE("result name: %s", result->_name.GetCString()); // パラメータのタイプを取得し表示する TRACE("result type: %d", result->_type); // パラメータの値を取得し表示する (パラメータの値は 6.0 になる) TRACE("result value: %s", ACharConstPtr(result->_value.GetBuffer())); } // 方法 3: soap 引数の値(SFXSOAPParser 型)から SOAP-RPC の結果を取得する // ※ SOAP-RPC の結果 = SOAP メッセージの Body 要素(SOAP Body)の第 1 子要素の第 1 子要素 SFXXMLElementPtr response = soap.GetRPCResult(); // SOAP-RPC の結果を取得し表示する TRACE("result value: %s", response->GetText().GetCString()); } // サーバ側からのエラーメッセージを取得する 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 要素が null でない場合 if (fault._faultdetail) { // detail 要素を表示する TRACE("faultstring: %s", fault._faultdetail->GetText().GetCString()); } } return; }
以下は、加減乗除を行う Web サービスを定義する WSDL 文書(ファイル名: "Arithmetic.wsdl")です。
注意 | |
---|---|
この Web サービスは、www.s-cradle.com でサンプルとして利用可能です。 |
<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:ns1="http://org.apache.axis2/xsd" xmlns:wsaw="http://www.w3.org/2006/05/addressing/wsdl" xmlns:http="http://schemas.xmlsoap.org/wsdl/http/" xmlns:ns0="http://soapsample.s_cradle.com" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" targetNamespace="http://soapsample.s_cradle.com"> <wsdl:types> <xs:schema xmlns:ns="http://soapsample.s_cradle.com" attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://soapsample.s_cradle.com"> <xs:element name="Add"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="left" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="right" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="AddResponse"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Divide"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="left" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="right" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="DivideResponse"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Multiply"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="left" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="right" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="MultiplyResponse"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="Substract"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="left" nillable="true" type="xs:string"/> <xs:element minOccurs="0" name="right" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> <xs:element name="SubstractResponse"> <xs:complexType> <xs:sequence> <xs:element minOccurs="0" name="return" nillable="true" type="xs:string"/> </xs:sequence> </xs:complexType> </xs:element> </xs:schema> </wsdl:types> <wsdl:message name="SubstractRequest"> <wsdl:part name="parameters" element="ns0:Substract"/> </wsdl:message> <wsdl:message name="SubstractResponse"> <wsdl:part name="parameters" element="ns0:SubstractResponse"/> </wsdl:message> <wsdl:message name="AddRequest"> <wsdl:part name="parameters" element="ns0:Add"/> </wsdl:message> <wsdl:message name="AddResponse"> <wsdl:part name="parameters" element="ns0:AddResponse"/> </wsdl:message> <wsdl:message name="DivideRequest"> <wsdl:part name="parameters" element="ns0:Divide"/> </wsdl:message> <wsdl:message name="DivideResponse"> <wsdl:part name="parameters" element="ns0:DivideResponse"/> </wsdl:message> <wsdl:message name="MultiplyRequest"> <wsdl:part name="parameters" element="ns0:Multiply"/> </wsdl:message> <wsdl:message name="MultiplyResponse"> <wsdl:part name="parameters" element="ns0:MultiplyResponse"/> </wsdl:message> <wsdl:portType name="ArithmeticPortType"> <wsdl:operation name="Substract"> <wsdl:input message="ns0:SubstractRequest" wsaw:Action="urn:Substract"/> <wsdl:output message="ns0:SubstractResponse" wsaw:Action="urn:SubstractResponse"/> </wsdl:operation> <wsdl:operation name="Add"> <wsdl:input message="ns0:AddRequest" wsaw:Action="urn:Add"/> <wsdl:output message="ns0:AddResponse" wsaw:Action="urn:AddResponse"/> </wsdl:operation> <wsdl:operation name="Divide"> <wsdl:input message="ns0:DivideRequest" wsaw:Action="urn:Divide"/> <wsdl:output message="ns0:DivideResponse" wsaw:Action="urn:DivideResponse"/> </wsdl:operation> <wsdl:operation name="Multiply"> <wsdl:input message="ns0:MultiplyRequest" wsaw:Action="urn:Multiply"/> <wsdl:output message="ns0:MultiplyResponse" wsaw:Action="urn:MultiplyResponse"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="ArithmeticSOAP11Binding" type="ns0:ArithmeticPortType"> <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <wsdl:operation name="Substract"> <soap:operation soapAction="urn:Substract" style="document"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Add"> <soap:operation soapAction="urn:Add" style="document"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Divide"> <soap:operation soapAction="urn:Divide" style="document"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Multiply"> <soap:operation soapAction="urn:Multiply" style="document"/> <wsdl:input> <soap:body use="literal"/> </wsdl:input> <wsdl:output> <soap:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:binding name="ArithmeticSOAP12Binding" type="ns0:ArithmeticPortType"> <soap12:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/> <wsdl:operation name="Substract"> <soap12:operation soapAction="urn:Substract" style="document"/> <wsdl:input> <soap12:body use="literal"/> </wsdl:input> <wsdl:output> <soap12:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Add"> <soap12:operation soapAction="urn:Add" style="document"/> <wsdl:input> <soap12:body use="literal"/> </wsdl:input> <wsdl:output> <soap12:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Divide"> <soap12:operation soapAction="urn:Divide" style="document"/> <wsdl:input> <soap12:body use="literal"/> </wsdl:input> <wsdl:output> <soap12:body use="literal"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Multiply"> <soap12:operation soapAction="urn:Multiply" style="document"/> <wsdl:input> <soap12:body use="literal"/> </wsdl:input> <wsdl:output> <soap12:body use="literal"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:binding name="ArithmeticHttpBinding" type="ns0:ArithmeticPortType"> <http:binding verb="POST"/> <wsdl:operation name="Substract"> <http:operation location="Arithmetic/Substract"/> <wsdl:input> <mime:content type="text/xml" part="Substract"/> </wsdl:input> <wsdl:output> <mime:content type="text/xml" part="Substract"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Add"> <http:operation location="Arithmetic/Add"/> <wsdl:input> <mime:content type="text/xml" part="Add"/> </wsdl:input> <wsdl:output> <mime:content type="text/xml" part="Add"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Divide"> <http:operation location="Arithmetic/Divide"/> <wsdl:input> <mime:content type="text/xml" part="Divide"/> </wsdl:input> <wsdl:output> <mime:content type="text/xml" part="Divide"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="Multiply"> <http:operation location="Arithmetic/Multiply"/> <wsdl:input> <mime:content type="text/xml" part="Multiply"/> </wsdl:input> <wsdl:output> <mime:content type="text/xml" part="Multiply"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="Arithmetic"> <wsdl:port name="ArithmeticSOAP11port_http" binding="ns0:ArithmeticSOAP11Binding"> <soap:address location="/soapsample/Arithmetic"/> </wsdl:port> <wsdl:port name="ArithmeticSOAP12port_http" binding="ns0:ArithmeticSOAP12Binding"> <soap12:address location="/soapsample/Arithmetic"/> </wsdl:port> <wsdl:port name="ArithmeticHttpport" binding="ns0:ArithmeticHttpBinding"> <http:address location="/soapsample/Arithmetic"/> </wsdl:port> </wsdl:service> </wsdl:definitions>
以下は、 SFXSOAPServiceProxy クラスを使用して、 WSDL 文書(ファイル名: "Arithmetic.wsdl")から SOAP-RPC プロキシを生成し、 ダイナミックバイディングを行うコードです。
例 19.24. WSDL 文書から SOAP-RPC プロキシを生成し、ダイナミックバイディングを行うコード
SFMTYPEDEFCLASS(xmlexplainer) class xmlexplainer : public SFCApplication { SFMSEALCOPY(xmlexplainer) private: // SFXSOAPServiceProxy オブジェクトはクラス変数にする SFXSOAPServiceProxy _wsdl; public: static SFCInvokerPtr Factory(Void); private: explicit xmlexplainer(Void) static_throws; virtual ~xmlexplainer(Void); virtual Bool HandleEvent(SFXEventConstRef event); virtual Bool HandleRender(SFXEventConstRef event); Void _SFXSOAPServiceProxy(Void); // サーバから返答を受け取るためのコールバック関数(エントリ) static Void OnResultSHP_WSDL(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap, VoidPtr reference); // サーバから返答を受け取るためのコールバック関数(本体) Void OnResult_WSDL(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap); }; Void xmlexplainer::_SFXSOAPServiceProxy(Void) { // www.s-cradle.com の "Arithmetic" サービスにアクセスするコード: // ※ 組み込み向けシステムの場合、メモリの制約から、WSDL ファイルのサイズは小さい方が望ましい // SFXSOAPServiceProxy クラスが自動生成する SOAP-RPC リクエストメッセージの内容: 2.0 と 3.0 の積を求める // <?xml version="1.0" encoding="UTF-8"?> // <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> // <SOAP-ENV:Body> // <Multiply xmlns="http://soapsample.s-cradle.com"> // <left>2.0</left> // <right>3.0</right> // </Multiply> // </SOAP-ENV:Body> // </SOAP-ENV:Envelope> // サーバから返答を受け取るためのコールバック関数(エントリ)を設定する // ※ コールバック関数は静的関数でなければいけないので、一旦 OnResultSHP_WSDL 静的関数を呼び出し、 // OnResultSHP_WSDL() 内からコールバック関数の本体である OnResult_WSDL メンバ関数を呼び出す _wsdl.SetNotifyHandler(OnResultSHP_WSDL, this); // Webサービス記述言語 WSDL を設定する if (_wsdl.SetWSDLDocument("Arithmetic.wsdl") == SFERR_NO_ERROR) { // Web サービスの名前を設定する _wsdl.SetServiceName("Arithmetic"); // Web サービスのポート名を設定する _wsdl.SetPortName("ArithmeticSOAP11port_http"); // 呼び出す Web サービスの機能 (メソッド) を設定する // ※ この場合、掛け算の結果を求める _wsdl.SetMethodName("Multiply"); // 指定されたパラメータの値を設定する _wsdl.SetParameterValue("left", SFXBuffer(SFXAnsiString("2.0"))); _wsdl.SetParameterValue("right", SFXBuffer(SFXAnsiString("3.0"))); // Web サービスを呼び出す _wsdl.Invoke(); } return; } // サーバから返答を受け取るためのコールバック関数(エントリ) Void xmlexplainer::OnResultSHP_WSDL(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap, VoidPtr reference) { // サーバから返答を受け取るためのコールバック関数(実体)を呼び出す static_cast<xmlexplainerPtr>(reference)->OnResult_WSDL(error, result, fault, soap); } // サーバから返答を受け取るためのコールバック関数(実体) Void xmlexplainer::OnResult_WSDL(SFCError error, const SFXSOAPRPC::Params& result, const SFXSOAPRPC::FAULT& fault, SFXSOAPParserConstRef soap) { // サーバから受け取った SOAP-RPC リクエストメッセージの内容は以下の通り: 結果の 6.0 が返却される // <?xml version="1.0" encoding="utf-8"?> // <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> // <soapenv:Body> // <ns:MultiplyResponse xmlns:ns="http://soapsample.s_cradle.com"> // <ns:return>6.0</ns:return> // </ns:MultiplyResponse> // </soapenv:Body> // </soapenv:Envelope> // SOAP-RPC 通信が成功したか判断する if (error == SFERR_NO_ERROR) { // 方法 1: result 引数の値(SFXSOAPRPC::Params 配列)から各要素の値を取得する // ※ SOAP-RPC の結果は SFXSOAPRPC::Params 配列に格納されている // SFXSOAPRPC::Params 配列の列挙子を取得する 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())); } } // 方法 2: SFXSOAPServiceProxy::GetResultValueByName 関数で特定のパラメータを取得する // 指定した名前を持つメソッドレスポンス(SFXSOAPRPC::PARAMETER 構造体)を取得する SFXSOAPRPC::LPPARAMETER result = _wsdl.GetResultValueByName("return"); if (result) { // パラメータの名前を取得し表示する パラメータの名前は "return" になる TRACE("result name: %s", result->_name.GetCString()); // パラメータのタイプを取得し表示する TRACE("result type: %d", result->_type); // パラメータの値を取得し表示する (パラメータの値は 6.0 になる) TRACE("result value: %s", ACharConstPtr(result->_value.GetBuffer())); } // 方法 3: soap 引数の値(SFXSOAPParser 型)から SOAP-RPC の結果を取得する // ※ SOAP-RPC の結果 = SOAP メッセージの Body 要素(SOAP Body)の第 1 子要素の第 1 子要素 SFXXMLElementPtr response = soap.GetRPCResult(); // SOAP-RPC の結果を取得し表示する TRACE("result value: %s", response->GetText().GetCString()); } // サーバ側からのエラーメッセージを取得する 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 要素が null でない場合 if (fault._faultdetail) { // detail 要素を表示する TRACE("faultstring: %s", fault._faultdetail->GetText().GetCString()); } } return; }
表 19.22. WSDL エラーメッセージ
値 | 解説 |
---|---|
SFERR_WSDL_EXPECT_SERVICE(0x69A6) | WSDL 文書に指定された service 要素がありません。 |
SFERR_WSDL_EXPECT_PORT(0x69A7) | WSDL 文書に指定された service 要素の port 要素がありません。 |
SFERR_WSDL_EXPECT_BINDING(0x69A8) | WSDL 文書に指定された service 要素の port 要素に binding 属性がありません。 |
SFERR_WSDL_EXPECT_OPERATION(0x69A9) | WSDL 文書に指定された service 要素の operation 要素(メソッド)がありません。 |
SFERR_WSDL_EXPECT_PORTTYPE(0x69AA) | WSDL 文書に指定された service 要素の port 要素の binding 属性の binding 要素の type 属性の portType 要素がありません。 |
SFERR_WSDL_EXPECT_MESSAGE(0x69AB) | WSDL 文書に指定された service 要素の operation 要素(メソッド)に input / output 要素がありません。 |
EFSFULL(0x0106) | ファイルシステムに空き容量がありません。 |
XML エラーメッセージ | |
---|---|
参照: SFCErrorEnum |
Copyright(c) 2002 - 2024 Sophia Cradle Incorporated All Rights Reserved. |