Class: Yast::XMLClass

Inherits:
Module
  • Object
show all
Includes:
Logger
Defined in:
library/xml/src/modules/XML.rb

Instance Method Summary collapse

Instance Method Details

#mainObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'library/xml/src/modules/XML.rb', line 55

def main
  # Sections in XML file that should be treated as CDATA when saving
  @cdataSections = []

  # How to call a list entry in the XML output
  @listEntries = {}

  # The system ID, or the DTD URI
  @systemID = nil

  # root element of the XML file
  @rootElement = ""

  # Global Namespace xmlns=...
  @nameSpace = "http://www.suse.com/1.0/yast2ns"

  # Type name space xmlns:config for YCP data (http://www.suse.com/1.0/configns)
  @typeNamespace = "http://www.suse.com/1.0/configns"

  @docs = {}
end

#validate(xml, schema) ⇒ Array<String>

Validates a XML document against a given schema.

Parameters:

  • xml (Pathname, String)

    path or content of XML (if the string contains a new line character it is considered as a XML string, otherwise as a file name)

  • schema (Pathname, String)

    path or content of relax ng schema

Returns:

  • (Array<String>)

    array of strings with errors or empty array if well formed and valid

Raises:



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'library/xml/src/modules/XML.rb', line 203

def validate(xml, schema)
  xml = SCR.Read(path(".target.string"), xml.to_s) if xml.is_a?(Pathname)
  if schema.is_a?(::String)
    validator = Nokogiri::XML::RelaxNG(schema)
  else
    schema_content = SCR.Read(path(".target.string"), schema.to_s)
    schema_path = File.dirname(schema)
    # change directory so relative include works
    Dir.chdir(schema_path) { validator = Nokogiri::XML::RelaxNG(schema_content) }
  end

  doc = Nokogiri::XML(xml, &:strict)
  validator.validate(doc).map(&:message)
rescue Nokogiri::XML::SyntaxError => e
  raise XMLDeserializationError, e.message
end

#xmlCreateDoc(doc, doc_settings) ⇒ void

This method returns an undefined value.

define a new doc type with custom settings, if not defined, global settings will be used.

Parameters:

  • symbol

    Document type identifier

  • map

    Document type Settings



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'library/xml/src/modules/XML.rb', line 82

def xmlCreateDoc(doc, doc_settings)
  doc_settings = deep_copy(doc_settings)
  current_settings = {
    "cdataSections" => Ops.get_list(
      doc_settings,
      "cdataSections",
      @cdataSections
    ),
    "systemID"      => doc_settings["systemID"],
    "rootElement"   => Ops.get_string(
      doc_settings,
      "rootElement",
      @rootElement
    ),
    "listEntries"   => Ops.get_map(doc_settings, "listEntries", @listEntries)
  }
  if Ops.get_string(doc_settings, "typeNamespace", "") != ""
    Ops.set(
      current_settings,
      "typeNamespace",
      Ops.get_string(doc_settings, "typeNamespace", "")
    )
  end

  if Ops.get_string(doc_settings, "nameSpace", "") != ""
    Ops.set(
      current_settings,
      "nameSpace",
      Ops.get_string(doc_settings, "nameSpace", "")
    )
  end
  Ops.set(@docs, doc, current_settings)
  nil
end

#XMLErrorObject

Deprecated.

Exception is used instead

The error string from the XML parser. It should be used when the agent did not return content. A reset happens before a new XML parsing starts.

Returns:

  • nil



225
226
227
# File 'library/xml/src/modules/XML.rb', line 225

def XMLError
  nil
end

#XMLToYCPFile(xml_file) ⇒ Hash

Reads XML file

Parameters:

  • xml_file (String)

    XML file name to read

Returns:

  • (Hash)

    parsed content

Raises:



167
168
169
170
171
172
173
# File 'library/xml/src/modules/XML.rb', line 167

def XMLToYCPFile(xml_file)
  raise ArgumentError, "XMLToYCPFile() received nil" if xml_file.nil?
  raise XMLDeserializationError, "Cannot find XML file #{xml_file}" if SCR.Read(path(".target.size"), xml_file) <= 0

  log.info "Reading #{xml_file}"
  XMLToYCPString(SCR.Read(path(".target.string"), xml_file))
end

#XMLToYCPString(xml_string) ⇒ Hash

Reads XML string

Parameters:

  • xml_string (String)

    to read

Returns:

  • (Hash)

    parsed content

Raises:



179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'library/xml/src/modules/XML.rb', line 179

def XMLToYCPString(xml_string)
  raise XMLDeserializationError, "Cannot convert empty XML string" if !xml_string || xml_string.empty?

  doc = Nokogiri::XML(xml_string, &:strict)
  doc.remove_namespaces! # remove fancy namespaces to make user life easier

  result = {}
  # inspect only element nodes
  doc.root.children.select(&:element?).each { |n| parse_node(n, result) }

  result
rescue Nokogiri::XML::SyntaxError => e
  raise XMLDeserializationError, e.message
end

#YCPToXMLFile(doc_type, contents, output_path) ⇒ Boolean

YCPToXMLFile() Write YCP data into formated XML file

Parameters:

  • doc_type (Symbol)

    Document type identifier

  • contents (Hash)

    a map with YCP data

  • output_path (String)

    the path of the XML file

Returns:

  • (Boolean)

    true on sucess

Raises:



124
125
126
127
128
129
# File 'library/xml/src/modules/XML.rb', line 124

def YCPToXMLFile(doc_type, contents, output_path)
  xml = YCPToXMLString(doc_type, contents)
  return false unless xml

  SCR.Write(path(".target.string"), output_path, xml)
end

#YCPToXMLString(doc_type, contents) ⇒ String?

Write YCP data into formated XML string

Parameters:

  • doc_type (Symbol)

    Document type identifier

  • contents (Hash)

    a map with YCP data

Returns:

  • (String, nil)

    String with XML data or nil if error happen

Raises:



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'library/xml/src/modules/XML.rb', line 136

def YCPToXMLString(doc_type, contents)
   = @docs[doc_type]
  if !
    log.error "Calling YCPToXML with unknown doc_type #{doc_type.inspect}. " \
              "Known types #{@docs.keys.inspect}"
    return nil
  end

  doc = Nokogiri::XML::Document.new("1.0")
  root_name = ["rootElement"]
  if !root_name || root_name.empty?
    log.warn "root element missing in docs #{.inspect}"
    return nil
  end

  doc.create_internal_subset(root_name, nil, ["systemID"])

  root = doc.create_element root_name
  root.default_namespace = ["nameSpace"] if ["nameSpace"]
  root.add_namespace("config", ["typeNamespace"]) if ["typeNamespace"]

  add_element(doc, , root, contents)

  doc.root = root
  doc.to_xml
end