как создать генератор древовидной структуры с рубином в файле xml?

Я работаю над проектом, в котором мне нужно создать пакет msi из Ubuntu для Windows.

Мне удалось создать файл msi из Ubuntu rgace в «msitools», который использует файлы wxs (это похоже на файл xml) для настройки пакета.

Пример файла wxs, который занимает один файл (FoobarAppl10.exe).

      <?xml version='1.0' encoding='windows-1252'?>
<Wix xmlns='http://schemas.microsoft.com/wix/2006/wi'>
  <Product Name='Foobar 1.0' Id='ABCDDCBA-86C7-4D14-AEC0-86416A69ABDE' UpgradeCode='ABCDDCBA-7349-453F-94F6-BCB5110BA4FD'
    Language='1033' Codepage='1252' Version='1.0.0' Manufacturer='Acme Ltd.'>

<Package Id='*' Keywords='Installer' Description="Acme's Foobar 1.0 Installer"
  Comments='Foobar is a registered trademark of Acme Ltd.' Manufacturer='Acme Ltd.'
  InstallerVersion='100' Languages='1033' Compressed='yes' SummaryCodepage='1252' />

<Media Id='1' Cabinet='Sample.cab' EmbedCab='yes' DiskPrompt="CD-ROM #1" />
<Property Id='DiskPrompt' Value="Acme's Foobar 1.0 Installation [1]" />

<Directory Id='TARGETDIR' Name='SourceDir'>
  <Directory Id='ProgramFilesFolder' Name='PFiles'>
    <Directory Id='Acme' Name='Acme'>
      <Directory Id='INSTALLDIR' Name='Foobar 1.0'>

        <Component Id='MainExecutable' Guid='ABCDDCBA-83F1-4F22-985B-FDB3C8ABD471'>
          <File Id='FoobarEXE' Name='FoobarAppl10.exe' DiskId='1' Source='FoobarAppl10.exe' KeyPath='yes'/>
        </Component>

      </Directory>
    </Directory>
  </Directory>
</Directory>

<Feature Id='Complete' Level='1'>
  <ComponentRef Id='MainExecutable' />
</Feature>
</Product>
</Wix>

Теперь моя проблема состоит в том, чтобы создать генератор древовидной структуры с рубином, чтобы мой файл wxs упаковывал все файлы моего проекта, не записывая его вручную.

Я пишу код, который может создать файл xml и распечатать мой брут-код:

$ лс

build.wxs foobarAppl10.exe генератор_xml.rb

      require 'nokogiri'

out_file = File.new("generated.wxs", "w")

builder = Nokogiri::XML::Builder.new(:encoding => 'windows-1252') { |xml|
  xml.Wix('xmlns' => 'http://schemas.microsoft.com/wix/2006/wi') do
    xml.Product('Name' => 'Foobar 1.0', 'Id' => 'ABCDDCBA-86C7-4D14-AEC0-86416A69ABDE',
    'UpgradeCode' =>'ABCDDCBA-7349-453F-94F6-BCB5110BA4FD',  'Language' => '1033', 'Codepage' => '1252',
    'Version' => '1.0.0', 'Manufacturer' => 'Acme Ltd.') do
      
      xml.Package('Id' => '*', 'Keywords' => 'Installer', 'Description' => "Acme's Foobar 1.0 Installer", 
      'Comments' => 'Foobar is a registered trademark of Acme Ltd.', 'Manufacturer' => 'Acme Ltd.',
      'InstallerVersion' => '100', 'Languages' => '1033', 'Compressed' => 'yes', 'SummaryCodepage' => '1252')
    
      xml.Media('Id' => '1', 'Cabinet' => 'Sample.cab', 'EmbedCab' => 'yes', 'DiskPrompt' => "CD-ROM #1")
    
      xml.Property('Id' => 'DiskPromt', 'Value' => "Acme's Foobar 1.0 Installation [1]")

      xml.Directory('Id' => 'TARGETDIR', 'Name' =>'SourceDir') do
        xml.Directory('Id' => 'ProgramFilesFolder', 'Name' =>'PFiles') do
          xml.Directory('Id' => 'Acme', 'Name' =>'Acme') do
            xml.Directory('Id' => 'INSTALLDIR', 'Name' =>'Foobar 1.0') do

              xml.Component('Id' => 'MainExecutable', 'Guid' => 'ABCDDCBA-83F1-4F22-985B-FDB3C8ABD471') do
            
                xml.File('Id' => 'FoobarEXE', 'Name' => 'FoobarAppl10.exe', 'DiskId' => '1', 'Source' => 'FoobarAppl10.exe', 'KeyPath' =>'yes')
            
              end

            end
          end
        end
      end
      xml.Feature('Id' => 'Complete', 'Level' => '1') do
        xml.Component('Id' => 'MainExecutable')
      end
    end
  end
}

puts builder.to_xml

out_file.puts(builder.to_xml)
out_file.close

Если кто-то знает, как генерировать код из древовидной структуры, это мне очень поможет!

1 ответ

Похоже, вы хотите создать структуру XML, которая имитирует структуру каталогов? Вот рекурсивная функция, которая должна делать большую часть того, что вы хотите, или, по крайней мере, служить хорошей отправной точкой. операторы могут быть удалены или заменены любыми другими действиями, которые вам необходимо выполнить, когда вы найдете каталог или файл.

      require 'nokogiri'

def process_dir(current_path, xml)
    return if !File.directory?(current_path) || Dir.empty?(current_path)
    directory_name = current_path.split("/").last
    # insert code here to compute other attributes for Directory node
    xml.Directory(Name: directory_name) do
        Dir.children(current_path).each do |entry| 
            file = "#{current_path}/#{entry}"
            if !File.directory?(file)
                # insert code here to compute other attributes for File node
                xml.File(Name: entry)
                puts "found file named #{entry} at #{current_path}"
            else
                puts "found directory named #{current_path}/#{entry}"
                process_dir("#{current_path}/#{entry}", xml)
            end
        end
    end
end

builder = Nokogiri::XML::Builder.new do |xml|
    xml.root { process_dir(".", xml) }
end

pp builder.to_xml
Другие вопросы по тегам