note description: "Objects that provide useful utilities for XML." legal: "See notice at end of class." status: "See notice at end of class." author: "" date: "$Date$" revision: "$Revision$" class GB_XML_UTILITIES inherit ANY GB_CONSTANTS export {NONE} all end BASIC_ROUTINES feature -- Access new_child_element (a_parent: XM_COMPOSITE; a_name, a_ns_prefix: STRING): XM_ELEMENT -- `Result' is a new child element with name `a_name' and ns_prexif `a_ns_prefix'. require parent_not_void: a_parent /= Void name_not_void: a_name /= Void do create Result.make (a_parent, a_name, create {XM_NAMESPACE}.make (a_ns_prefix, "")) ensure Result_not_void: Result /= Void end add_attribute_to_element (element: XM_ELEMENT; a_name, a_prefix, a_value: STRING) -- Add an atribute with name `a_name', prefix `a_prefix' and value `a_value' to `element'. require element_not_void: element /= Void a_name_not_void: a_name /= Void a_prefix_not_void: a_prefix /= Void a_value_not_void: a_value /= Void local l_attribute: XM_ATTRIBUTE do create l_attribute.make (a_name, create {XM_NAMESPACE}.make_default, a_value, element) element.force_last (l_attribute) end add_element_containing_integer (element: XM_ELEMENT; element_name: STRING; value: INTEGER) -- Add an element named `element' containing integer data `value' to `element'. require element_not_void: element /= Void element_name_not_void: element_name /= Void element_name_not_empty: element_name.count >= 1 local new_element: XM_ELEMENT do new_element := new_child_element (element, element_name, "") element.force_last (new_element) add_string_data (new_element, value.out) end add_element_containing_integer_constant (element: XM_ELEMENT; element_name: STRING; constant: STRING) -- Add an element named `element' marked `constant', containing another element named `element_name' with -- constant named `constant'. This is the format used to store integer constants. require element_not_void: element /= Void element_name_not_void: element_name /= Void element_name_not_empty: element_name.count >= 1 local new_element, new_constant_element: XM_ELEMENT do new_constant_element := new_child_element (element, element_name, "") element.force_last (new_constant_element) new_element := new_child_element (new_constant_element, Constant_string, "") new_constant_element.force_last (new_element) add_string_data (new_element, constant) end add_element_containing_string (element: XM_ELEMENT; element_name: STRING; value: READABLE_STRING_GENERAL) -- Add an element named `element' containing string data `value' to `element'. require element_not_void: element /= Void element_name_not_void: element_name /= Void element_name_not_empty: element_name.count >= 1 value_not_void: value /= Void local new_element: XM_ELEMENT do new_element := new_child_element (element, element_name, "") element.force_last (new_element) add_string_data (new_element, value) end add_element_containing_boolean (element: XM_ELEMENT; element_name: STRING; value: BOOLEAN) -- Add an element named `element' containing boolean data `value' to `element'. require element_not_void: element /= Void element_name_not_void: element_name /= Void element_name_not_empty: element_name.count >= 1 local new_element: XM_ELEMENT do new_element := new_child_element (element, element_name, "") element.force_last (new_element) add_boolean_data (new_element, value) end add_boolean_data (element: XM_ELEMENT; content: BOOLEAN) -- Add boolean character data with content `content' to `element' require element_not_void: element /= Void local string_data: STRING do if content then string_data := True_string else string_data := False_string end add_string_data (element, string_data) end add_string_data (element: XM_ELEMENT; content: READABLE_STRING_GENERAL) -- Add string character data with content `content' to `element' require element_not_void: element /= Void content_not_void: content /= Void local new_element: XM_CHARACTER_DATA l_uc_string: UC_STRING do create l_uc_string.make_from_string_general (content.as_string_32) create new_element.make (element, l_uc_string) element.force_last (new_element) end create_widget_instance (element: XM_ELEMENT; widget_name: STRING): XM_ELEMENT -- Create a new instance of a widget `widget_name' in `element'. require element_not_void: element /= Void widget_name_not_void: widget_name /= Void widget_name_not_empty: widget_name.count >= 1 do Result := new_child_element (element, Item_string, "") add_attribute_to_element (Result, "type", "xsi", widget_name) ensure Result_not_void: Result /= Void end get_unique_full_info (element: XM_ELEMENT): HASH_TABLE [ELEMENT_INFORMATION, STRING] -- `Result' provides access to all child_elements and XML character -- data of `Current' referenced by their unique names. -- Ignores `item'. require element_not_void: element /= Void local current_element, inner_element: XM_ELEMENT current_data_element: XM_CHARACTER_DATA char_data: STRING info: ELEMENT_INFORMATION do create Result.make (8) from element.start until element.off loop current_element ?= element.item_for_iteration if current_element /= Void then if not current_element.name.same_string (Item_string) and not current_element.name.same_string ("item_text") then create info info.set_name (current_element.name) info.set_element (current_element) from current_element.start until current_element.off loop inner_element ?= current_element.item_for_iteration if inner_element /= Void then if inner_element.name.same_string (Constant_string) then from inner_element.start until inner_element.off loop current_data_element ?= inner_element.item_for_iteration if current_data_element /= Void then char_data := current_data_element.content if data_valid (char_data) then info.set_data (char_data) info.set_as_constant end end inner_element.forth end end end if not info.is_constant then current_data_element ?= current_element.item_for_iteration if current_data_element /= Void then char_data := current_data_element.content if data_valid (char_data) then info.set_data (char_data) end end end current_element.forth end Result.put (info, info.name) end end element.forth end ensure result_not_void: Result /= Void end all_child_element_names (element: XM_ELEMENT): ARRAYED_LIST [STRING] -- `Result' is a list of all names of the child elements of `element' require element_not_void: element /= Void local current_element: XM_ELEMENT do create Result.make (0) from element.start until element.off loop current_element ?= element.item_for_iteration if current_element /= Void then Result.extend (current_element.name) end element.forth end end child_element_by_name (element: XM_ELEMENT; a_name: STRING): XM_ELEMENT -- `Result' is child element of `element' with name equal to `a_name'. require element_not_void: element /= Void name_not_void_or_empty: a_name /= Void and then a_name.count > 0 local current_element: XM_ELEMENT found: BOOLEAN index: INTEGER do index := element.index from element.start until element.off or found loop current_element ?= element.item_for_iteration if current_element /= Void and then current_element.name.same_string (a_name) then found := True Result := current_element end element.forth end element.go_i_th (index) ensure cursor_not_moved: old element.index = element.index end string_from_xm_document (a_document: XM_DOCUMENT): STRING -- Return a string representation of XM document `a_document'. require a_document_not_void: a_document /= Void local pretty_print: XM_INDENT_PRETTY_PRINT_FILTER xmlns_generator: XM_XMLNS_GENERATOR output_stream: KL_STRING_OUTPUT_STREAM do create output_stream.make ("") create pretty_print.make_null pretty_print.set_output_stream (output_stream) create xmlns_generator.make_next (pretty_print) a_document.process_to_events (xmlns_generator) Result := output_stream.string ensure result_not_void: Result /= Void end add_tabs (a_string: STRING; index, count: INTEGER) -- Add `count' tab characters to `a_string' at index `index'. local counter: INTEGER temp_string: STRING do create temp_string.make (0) from counter := 1 until counter > count loop temp_string.append ("%T") counter := counter + 1 end a_string.append (temp_string)--insert_string (temp_string, index) ensure new_count_correct: a_string.count = old a_string.count + count end show_element (element: XM_ELEMENT; window: EV_TITLED_WINDOW) -- Show contents of `element' in a dialog displayed modally to `window'. require element_not_void: element /= Void window_not_void: window /= Void window_displayed: window.is_displayed local dialog: EV_DIALOG vertical_box: EV_VERTICAL_BOX text: EV_TEXT cancel_button: EV_BUTTON namespace: XM_NAMESPACE document: XM_DOCUMENT l_string: STRING do create namespace.make_default create document.make -- If we do not twin the element, the parent is changed which -- is a side effect that we do not wish. document.set_root_element (element.deep_twin) l_string := string_from_xm_document (document) create dialog dialog.set_minimum_size (400, 600) create vertical_box dialog.extend (vertical_box) create text vertical_box.extend (text) create cancel_button.make_with_text ("Cancel") vertical_box.extend (cancel_button) vertical_box.disable_item_expand (cancel_button) cancel_button.select_actions.extend (agent dialog.destroy) dialog.set_default_cancel_button (cancel_button) text.set_text (l_string) dialog.show_modal_to_window (window) end remove_nodes_recursive (element: XM_ELEMENT; node_name: STRING) -- Recursively remove all nodes named `node_name' from `element'. require element_not_void: element /= Void node_name_not_void: node_name /= Void local current_element: XM_ELEMENT current_name: STRING do from element.start until element.off loop current_element ?= element.item_for_iteration if current_element /= Void then current_name := current_element.name if current_name.same_string (node_name) then element.remove_at else remove_nodes_recursive (current_element, node_name) end end element.forth end end all_elements_by_name (element: XM_ELEMENT; node_name: STRING): ARRAYED_LIST [XM_ELEMENT] -- Recursively remove all nodes named `node_name' from `element'. require element_not_void: element /= Void node_name_not_void: node_name /= Void do create Result.make (10) all_elements_by_name_internal (element, node_name, Result) end all_elements_by_name_internal (element: XM_ELEMENT; node_name: STRING; elements: ARRAYED_LIST [XM_ELEMENT]) -- Recursively remove all nodes named `node_name' from `element'. require element_not_void: element /= Void node_name_not_void: node_name /= Void elements_not_void: elements /= Void local current_element: XM_ELEMENT current_name: STRING do from element.start until element.off loop current_element ?= element.item_for_iteration if current_element /= Void then current_name := current_element.name if current_name.same_string (node_name) then elements.extend (current_element) end all_elements_by_name_internal (current_element, node_name, elements) end element.forth end end feature {NONE} -- Implementation data_valid (current_data: STRING):BOOLEAN -- Is `current_data' not empty and valid? require data_not_void: current_data /= Void do if current_data.count > 0 then Result := True end end note copyright: "Copyright (c) 1984-2006, Eiffel Software" license: "GPL version 2 (see http://www.eiffel.com/licensing/gpl.txt)" licensing_options: "http://www.eiffel.com/licensing" copying: "[ This file is part of Eiffel Software's Eiffel Development Environment. Eiffel Software's Eiffel Development Environment is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License (available at the URL listed under "license" above). Eiffel Software's Eiffel Development Environment is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Eiffel Software's Eiffel Development Environment; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ]" source: "[ Eiffel Software 356 Storke Road, Goleta, CA 93117 USA Telephone 805-685-1006, Fax 805-685-6869 Website http://www.eiffel.com Customer support http://support.eiffel.com ]" end -- class XML_UTILITIES