Class: Lutaml::Xsd::Validation::XmlNavigator

Inherits:
Object
  • Object
show all
Defined in:
lib/lutaml/xsd/validation/xml_navigator.rb

Overview

XmlNavigator wraps Moxml for XML navigation with XPath tracking

This class provides a consistent interface for navigating XML documents while maintaining context for validation. It tracks the current position in the document tree and provides XPath information for error reporting.

Examples:

Parse and navigate XML

navigator = XmlNavigator.new(xml_content)
root = navigator.root_element
navigator.with_element(root) do
  puts navigator.current_xpath  # => "/root"
end

Access the document

doc = navigator.document
elements = doc.all_elements

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(xml_content, adapter: :nokogiri) ⇒ XmlNavigator

Initialize a new XmlNavigator

Parameters:

  • xml_content (String)

    The XML content to parse

  • adapter (Symbol) (defaults to: :nokogiri)

    The Moxml adapter to use (:nokogiri, :ox, :oga)

Raises:

  • (ArgumentError)

    if xml_content is nil or empty

  • (Moxml::ParseError)

    if XML parsing fails



36
37
38
39
40
41
42
43
44
45
46
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 36

def initialize(xml_content, adapter: :nokogiri)
  raise ArgumentError, "XML content cannot be nil" if xml_content.nil?

  if xml_content.empty?
    raise ArgumentError,
          "XML content cannot be empty"
  end

  @moxml_document = parse_xml(xml_content, adapter)
  @current_path = []
end

Instance Attribute Details

#current_pathObject (readonly)

Returns the value of attribute current_path.



27
28
29
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 27

def current_path
  @current_path
end

#moxml_documentObject (readonly)

Returns the value of attribute moxml_document.



27
28
29
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 27

def moxml_document
  @moxml_document
end

Instance Method Details

#at_root?Boolean

Check if currently at root

Returns:

  • (Boolean)


121
122
123
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 121

def at_root?
  @current_path.empty?
end

#current_xpathString

Get the current XPath location

Returns the XPath of the current position in the document tree based on the navigation context.

Returns:

  • (String)

    XPath string (e.g., “/root/child”)



68
69
70
71
72
73
74
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 68

def current_xpath
  return "/" if @current_path.empty?

  "/" + @current_path.map.with_index do |segment, idx|
    format_xpath_segment(segment, idx)
  end.join("/")
end

#depthInteger

Get the depth of the current position

Returns:

  • (Integer)

    The depth (0 for root, 1 for immediate children, etc.)



114
115
116
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 114

def depth
  @current_path.length
end

#documentXmlDocument

Get the XML document

Returns:



51
52
53
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 51

def document
  @document ||= XmlDocument.new(@moxml_document, self)
end

#inspectString

Detailed string representation

Returns:

  • (String)


161
162
163
164
165
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 161

def inspect
  "#<#{self.class.name} " \
    "current_xpath=#{current_xpath.inspect} " \
    "depth=#{depth}>"
end

#parent_xpathString?

Get the parent XPath

Returns:

  • (String, nil)

    Parent XPath or nil if at root



128
129
130
131
132
133
134
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 128

def parent_xpath
  return nil if @current_path.length <= 1

  "/" + @current_path[0..-2].map.with_index do |segment, idx|
    format_xpath_segment(segment, idx)
  end.join("/")
end

#resetvoid

This method returns an undefined value.

Reset navigation to root



139
140
141
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 139

def reset
  @current_path.clear
end

#root_elementXmlElement?

Get the root element

Returns:



58
59
60
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 58

def root_element
  document.root_element
end

#to_sString

Convert to string representation

Returns:

  • (String)


154
155
156
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 154

def to_s
  "XmlNavigator(xpath: #{current_xpath})"
end

#with_element(element) { ... } ⇒ Object

Execute a block within an element’s context

This method maintains the navigation path stack, adding the element to the path before executing the block and removing it afterwards.

Examples:

Navigate into an element

navigator.with_element(child_element) do
  # Current XPath is updated to include child_element
  navigator.validate_element
end

Parameters:

  • element (XmlElement)

    The element to navigate into

Yields:

  • Block to execute within element context

Returns:

  • (Object)

    Result of the block



90
91
92
93
94
95
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 90

def with_element(element)
  @current_path.push(build_path_segment(element))
  yield
ensure
  @current_path.pop
end

#with_indexed_element(element, index) { ... } ⇒ Object

Navigate to a specific element by index

Parameters:

  • element (XmlElement)

    The element to navigate to

  • index (Integer)

    The index of this element among siblings

Yields:

  • Block to execute within element context

Returns:

  • (Object)

    Result of the block



103
104
105
106
107
108
109
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 103

def with_indexed_element(element, index)
  segment = build_path_segment(element, index)
  @current_path.push(segment)
  yield
ensure
  @current_path.pop
end

#xpath(xpath_expr) ⇒ Array<XmlElement>

Find elements by XPath expression

Parameters:

  • xpath_expr (String)

    XPath expression

Returns:



147
148
149
# File 'lib/lutaml/xsd/validation/xml_navigator.rb', line 147

def xpath(xpath_expr)
  document.xpath(xpath_expr)
end