/* * $Id: XMLTool.cpp,v 1.3 2006/06/20 10:11:06 ozawa Exp $ * * Copyright 2005- ONGS Inc. All rights reserved. * * author: Masanori OZAWA (ozawa@ongs.co.jp) * version: $Revision: 1.3 $ * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY ONGS INC ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL ONGS INC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are * those of the authors and should not be interpreted as representing official * policies, either expressed or implied, of the ONGS Inc. * */ #include "xdtp.h" #include "XMLTool.h" #include "Utilities.h" #include "libxml/xmlmemory.h" #include "libxml/xmlIO.h" using namespace XDTP; XMLTool::XMLTool() { static bool init = false; if (!init) { xmlInitParser(); xmlSubstituteEntitiesDefault(1); xmlLoadExtDtdDefaultValue = 1; init = true; } } XMLTool::~XMLTool() { } /** * 複数階層に跨るElementを一度に生成します。 * 既存のElementが存在する場合は、存在しないElementのみを生成します。 * * @param aDocument * 生成対象のDOM オブジェクト * @param aXPath * 複数階層に跨るElementを識別するXPath。 * 1つの階層に複数のElementを指定するようなことはできません。(書式: /e1/e2/e3/e4 ) * @return 作成に成功したときは最下層の Element。失敗したときは null。 */ xmlNodePtr XMLTool::createElements(xmlDocPtr aDocument, const Glib::ustring& aXPath) { int count = 0; gchar **tokens = g_strsplit(aXPath.c_str(), "/", 0); xmlNodePtr node = NULL; xmlNodePtr parent = xmlDocGetRootElement(aDocument); if (!tokens) return NULL; if (!tokens[0] || !tokens[1]) { g_strfreev(tokens); return NULL; } if (xmlStrcmp(parent->name, (const xmlChar *)tokens[1])) { g_strfreev(tokens); return NULL; } node = parent->xmlChildrenNode; for (count = 2; tokens[count]; count++) { while (node && xmlStrcmp(node->name, (const xmlChar *)tokens[count])) { node = node->next; } if (node) { parent = node; node = parent->xmlChildrenNode; } else { // 新規に構築 node = xmlNewDocNode(aDocument, NULL, (xmlChar*)tokens[count], NULL); xmlAddChild(parent, node); parent = node; node = NULL; } } if (tokens[count]) { parent = NULL; } g_strfreev(tokens); return parent; } /** * XMLファイルのエンコーディングを取得します。 * * @param aFile XMLファイル名 * @return エンコーディング */ std::string XMLTool::getEncoding(const Glib::ustring& aFile) { std::string result; // XML文章のエンコードを取得する try { Glib::ustring line; Glib::ustring::size_type pos; Glib::RefPtr ioc = Glib::IOChannel::create_from_file(aFile.c_str(), "r"); ioc->set_encoding("ASCII"); while (ioc->read_line(line) == Glib::IO_STATUS_NORMAL) { if (!line.empty()) { line = Utilities::strTrim(line); line = line.lowercase(); if ("close(); } catch (Glib::Error error) { std::string msg = Glib::locale_from_utf8(error.what()); fprintf(stderr, "%s: %s" LINE_SEP, APP_NAME, msg.c_str()); } catch (...) { fprintf(stderr, "%s: XMLTool: Unable to read the XML file. (%s)" LINE_SEP, APP_NAME, aFile.c_str()); } return result; } /** * Nodeからの相対XPath指定で得られるNodeの一覧を取得します。 * * @param aNode * 探索元のNode * @param aXPath * Nodeからの相対XPath * @return 取得したNodeの一覧を保持するオブジェクト。 * 不要になった段階で、xmlXPathFreeObjectする必要があります。 */ xmlXPathObjectPtr XMLTool::getNodeList(xmlNodePtr aNode, const Glib::ustring& aXPath) { if (!aNode) return NULL; xmlXPathContextPtr xpathCtx = xmlXPathNewContext(aNode->doc); xmlXPathObjectPtr xpathObj; if (!xpathCtx) return NULL; xpathCtx->node = aNode; // set the current node xpathObj = xmlXPathEvalExpression((const xmlChar*)aXPath.c_str(), xpathCtx); xmlXPathFreeContext(xpathCtx); if (!xpathObj) { return NULL; } if (xmlXPathNodeSetIsEmpty(xpathObj->nodesetval)) { xmlXPathFreeObject(xpathObj); return NULL; } return xpathObj; } /** * Nodeの直下に存在するTextを取得します。 * * @param aNode * Textを含んだNode * @return 取得したTextの文字列。Textが存在しない場合は空文字列。 */ Glib::ustring XMLTool::getText(xmlNodePtr aNode) { Glib::ustring result; xmlChar *text = xmlNodeListGetString(aNode->doc, aNode->xmlChildrenNode, 1); if (text) { result = (char*)text; xmlFree(text); } return result; } /** * NodeがAttributeかチェックします。 * * @param aNode * チェック対象のNode * @return Attributeの場合は true */ bool XMLTool::isAttribute(xmlNodePtr aNode) { return (XML_ATTRIBUTE_NODE == aNode->type); } /** * NodeがCommentかチェックします。 * * @param aNode * チェック対象のNode * @return Commentの場合は true */ bool XMLTool::isComment(xmlNodePtr aNode) { return (XML_COMMENT_NODE == aNode->type); } /** * NodeがElementかチェックします。 * * @param aNode * チェック対象のNode * @return Elementの場合は true */ bool XMLTool::isElement(xmlNodePtr aNode) { return (XML_ELEMENT_NODE == aNode->type); } /** * NodeがTextかチェックします。 * * @param aNode * チェック対象のNode * @return Textの場合は true */ bool XMLTool::isText(xmlNodePtr aNode) { return (XML_TEXT_NODE == aNode->type); } /** * Nodeの直下にTextを設定します。 * * @param aNode * Textを設定するNode * @param aText * 設定するText * @return 設定に成功した場合は true */ bool XMLTool::setText(xmlNodePtr aNode, const Glib::ustring& aText) { bool result = false; xmlNodePtr node = aNode->children; while (node) { if (isText(node)) { xmlNodeSetContent(node, (const xmlChar *)aText.c_str()); result = true; break; } node = node->next; } if (!result) { // Textノードを新規に構築 node = xmlNewDocText(aNode->doc, (xmlChar*)aText.c_str()); result = (xmlAddChild(aNode, node) ? true : false); } return result; } /** * DOMドキュメントを、XSLTを用いて変換します。 * * @param aDocument * 変換元のDOMドキュメント * @param aXSLFile * XSLファイル * @return 変換後のDOMドキュメント。不要になった段階でxmlFreeDocする必要があります。 */ xmlDocPtr XMLTool::transform(xmlDocPtr aDocument, const Glib::ustring& aXSLFile) { xsltStylesheetPtr xsl; xmlDocPtr result; xsl = xsltParseStylesheetFile((const xmlChar *)aXSLFile.c_str()); result = transform(aDocument, xsl); xsltFreeStylesheet(xsl); return result; } /** * DOMドキュメントを、XSLTを用いて変換します。 * * @param aDocument * 変換元のDOMドキュメント * @param aXSL * XSLオブジェクト * @return 変換後のDOMドキュメント。不要になった段階でxmlFreeDocする必要があります。 */ xmlDocPtr XMLTool::transform(xmlDocPtr aDocument, xsltStylesheetPtr aXSL) { return xsltApplyStylesheet(aXSL, aDocument, NULL); }