# # Filename:: include.rb # Description:: xml include, for projbuild # # Author:: Greg Smith # # #----------------------------------------------------------------------------- # Uses #----------------------------------------------------------------------------- require 'xml' #----------------------------------------------------------------------------- # Implementation #----------------------------------------------------------------------------- module Pipeline module XMLUtil # class LibXML::XML::Node # # DW - its far faster to call this since it doesn't iterate over all the attributes as per attributes.length # def attributes? # attributes.first # end # end class Include include Singleton def initialize( ) schema_filename = "$(toolsconfig)/projbuild/projbuild.xsd" Pipeline::Globals.instance().in_env do |e| schema_filename = e.subst(schema_filename) end set_schema(schema_filename) end def set_schema( schema_filename ) parser = XML::Parser.file(schema_filename) @schema = parser.parse @schema_elements = @schema.find( 'xs:element' ) @schema_elements_all = [] @schema_elements.each { |schema_node| next unless ( schema_node.attributes? ) @schema_elements_all << schema_node } end def allow_count( node_name, child_name ) @schema_elements_all.each { |schema_node| attributes = schema_node.attributes next if ( attributes['name'] != node_name ) schema_node_elements = schema_node.find("xs:complexType/xs:sequence/xs:element") schema_node_elements.each { |schema_elem| next unless ( schema_elem.attributes? ) attributes = schema_elem.attributes next if ( attributes['ref'] != child_name ) return -1 if attributes['maxOccurs'] == "unbounded" } schema_node_elements = nil } schema_elements = nil 1 end def merge_node( xml_node, xml_include ) if ( xml_include.attributes? ) then include_attributes = xml_include.attributes target_attributes = xml_node.attributes include_attributes.each do |attribute| target_attributes[attribute.name] = attribute.value end end text_nodes = xml_include.find("text()") if ( text_nodes.size > 0 ) then text_nodes.each do |text_node| next if ( text_node.content.strip == '' ) #xml_node << text_node.copy(false) # this leads to an segmentation fault # so copy by hand... for some libxml internals reason this does not lead to a segmentation fault! new_node = nil if (text_node.name=="text") xml_node.content = text_node.content else new_node = XML::Node.new(text_node.name) text_node.attributes.each { |attr| new_node.attributes = attr } new_node.content = text_node.content xml_node << new_node end end end text_nodes = nil xml_include.each do |node| next if node.name == "text" allowed = allow_count(xml_node.name,node.name) xml_dest = xml_node.find_first(node.name) if allowed == -1 or xml_dest == nil then xml_new = XML::Node.new(node.name) #temporary... makes it easier to read the xml... xml_node << ("\n" + " " * (node.path.split("/").size - 1)) xml_node << xml_new merge_node(xml_new,node) else merge_node(xml_dest,node) end end xml_node end def merge_file( xml_node, path ) parser = XML::Parser.file(path) doc = parser.parse xml_new = doc.root if doc.root["xinclude"] != nil then include_path = doc.root["xinclude"] Pipeline::Globals.instance().in_env do |e| include_path = e.subst(include_path) end merge_file(xml_new,include_path) end merge_node(xml_node,xml_new) end end end # XMLUtil module end # Pipeline module