moxml 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.rubocop_todo.yml +50 -14
 - data/Gemfile +1 -0
 - data/LICENSE.md +33 -0
 - data/README.adoc +69 -21
 - data/lib/moxml/adapter/base.rb +12 -0
 - data/lib/moxml/adapter/customized_rexml/formatter.rb +195 -0
 - data/lib/moxml/adapter/nokogiri.rb +1 -1
 - data/lib/moxml/adapter/oga.rb +21 -7
 - data/lib/moxml/adapter/rexml.rb +458 -0
 - data/lib/moxml/adapter.rb +1 -1
 - data/lib/moxml/attribute.rb +2 -2
 - data/lib/moxml/config.rb +12 -3
 - data/lib/moxml/document_builder.rb +13 -17
 - data/lib/moxml/element.rb +4 -4
 - data/lib/moxml/namespace.rb +1 -1
 - data/lib/moxml/version.rb +1 -1
 - data/spec/moxml/adapter/rexml_spec.rb +14 -0
 - data/spec/moxml/all_with_adapters_spec.rb +0 -2
 - data/spec/moxml_spec.rb +1 -1
 - data/spec/support/shared_examples/declaration.rb +1 -0
 - data/spec/support/shared_examples/edge_cases.rb +3 -3
 - data/spec/support/shared_examples/element.rb +3 -3
 - data/spec/support/shared_examples/examples/readme_examples.rb +72 -15
 - data/spec/support/shared_examples/integration.rb +2 -2
 - data/spec/support/shared_examples/xml_adapter.rb +169 -7
 - metadata +7 -3
 
| 
         @@ -55,7 +55,7 @@ RSpec.shared_examples "Moxml::Element" do 
     | 
|
| 
       55 
55 
     | 
    
         
             
                  end
         
     | 
| 
       56 
56 
     | 
    
         | 
| 
       57 
57 
     | 
    
         
             
                  it "sets namespace" do
         
     | 
| 
       58 
     | 
    
         
            -
                    ns = element.add_namespace("x", "http://example.org"). 
     | 
| 
      
 58 
     | 
    
         
            +
                    ns = element.add_namespace("x", "http://example.org").namespaces.first
         
     | 
| 
       59 
59 
     | 
    
         
             
                    element.namespace = ns
         
     | 
| 
       60 
60 
     | 
    
         
             
                    expect(element.namespace).to eq(ns)
         
     | 
| 
       61 
61 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -79,8 +79,8 @@ RSpec.shared_examples "Moxml::Element" do 
     | 
|
| 
       79 
79 
     | 
    
         
             
                    expect(element.text).to eq("firstsecond")
         
     | 
| 
       80 
80 
     | 
    
         
             
                  end
         
     | 
| 
       81 
81 
     | 
    
         | 
| 
       82 
     | 
    
         
            -
                  it "sets inner  
     | 
| 
       83 
     | 
    
         
            -
                    element. 
     | 
| 
      
 82 
     | 
    
         
            +
                  it "sets inner XML" do
         
     | 
| 
      
 83 
     | 
    
         
            +
                    element.inner_xml = "<child>text</child>"
         
     | 
| 
       84 
84 
     | 
    
         
             
                    expect(element.children.size).to eq(1)
         
     | 
| 
       85 
85 
     | 
    
         
             
                    expect(element.children.first.name).to eq("child")
         
     | 
| 
       86 
86 
     | 
    
         
             
                    expect(element.children.first.text).to eq("text")
         
     | 
| 
         @@ -1,20 +1,25 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            RSpec.shared_examples "README Examples" do
         
     | 
| 
       4 
     | 
    
         
            -
              describe " 
     | 
| 
      
 4 
     | 
    
         
            +
              describe "Basic document creation" do
         
     | 
| 
       5 
5 
     | 
    
         
             
                it "builds document as shown in README" do
         
     | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
      
 6 
     | 
    
         
            +
                  doc = Moxml.new.create_document
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  # Add XML declaration
         
     | 
| 
      
 9 
     | 
    
         
            +
                  doc.add_child(doc.create_declaration("1.0", "UTF-8"))
         
     | 
| 
       8 
10 
     | 
    
         | 
| 
      
 11 
     | 
    
         
            +
                  # Create root element with namespace
         
     | 
| 
       9 
12 
     | 
    
         
             
                  root = doc.create_element("book")
         
     | 
| 
      
 13 
     | 
    
         
            +
                  root.add_namespace("dc", "http://purl.org/dc/elements/1.1/")
         
     | 
| 
       10 
14 
     | 
    
         
             
                  doc.add_child(root)
         
     | 
| 
       11 
15 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                   
     | 
| 
      
 16 
     | 
    
         
            +
                  # Add content
         
     | 
| 
       13 
17 
     | 
    
         
             
                  title = doc.create_element("dc:title")
         
     | 
| 
       14 
     | 
    
         
            -
                  title. 
     | 
| 
      
 18 
     | 
    
         
            +
                  title.text = "XML Processing with Ruby"
         
     | 
| 
       15 
19 
     | 
    
         
             
                  root.add_child(title)
         
     | 
| 
       16 
20 
     | 
    
         | 
| 
       17 
21 
     | 
    
         
             
                  expect(doc.to_xml).to include(
         
     | 
| 
      
 22 
     | 
    
         
            +
                    '<?xml version="1.0" encoding="UTF-8"?>',
         
     | 
| 
       18 
23 
     | 
    
         
             
                    '<book xmlns:dc="http://purl.org/dc/elements/1.1/">',
         
     | 
| 
       19 
24 
     | 
    
         
             
                    "<dc:title>XML Processing with Ruby</dc:title>",
         
     | 
| 
       20 
25 
     | 
    
         
             
                    "</book>"
         
     | 
| 
         @@ -22,7 +27,42 @@ RSpec.shared_examples "README Examples" do 
     | 
|
| 
       22 
27 
     | 
    
         
             
                end
         
     | 
| 
       23 
28 
     | 
    
         
             
              end
         
     | 
| 
       24 
29 
     | 
    
         | 
| 
       25 
     | 
    
         
            -
              describe " 
     | 
| 
      
 30 
     | 
    
         
            +
              describe "Using the builder pattern" do
         
     | 
| 
      
 31 
     | 
    
         
            +
                it "builds a correct document" do
         
     | 
| 
      
 32 
     | 
    
         
            +
                  doc = Moxml::Builder.new(Moxml.new).build do
         
     | 
| 
      
 33 
     | 
    
         
            +
                    declaration version: "1.0", encoding: "UTF-8"
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                    element "library", xmlns: "http://example.org/library" do
         
     | 
| 
      
 36 
     | 
    
         
            +
                      element "book" do
         
     | 
| 
      
 37 
     | 
    
         
            +
                        element "title" do
         
     | 
| 
      
 38 
     | 
    
         
            +
                          text "Ruby Programming"
         
     | 
| 
      
 39 
     | 
    
         
            +
                        end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                        element "author" do
         
     | 
| 
      
 42 
     | 
    
         
            +
                          text "Jane Smith"
         
     | 
| 
      
 43 
     | 
    
         
            +
                        end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                        comment "Publication details"
         
     | 
| 
      
 46 
     | 
    
         
            +
                        element "published", year: "2024"
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                        cdata "<custom>metadata</custom>"
         
     | 
| 
      
 49 
     | 
    
         
            +
                      end
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
                  end
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  expect(doc.to_xml).to include(
         
     | 
| 
      
 54 
     | 
    
         
            +
                    '<?xml version="1.0" encoding="UTF-8"?>',
         
     | 
| 
      
 55 
     | 
    
         
            +
                    '<library xmlns="http://example.org/library">',
         
     | 
| 
      
 56 
     | 
    
         
            +
                    "<title>Ruby Programming</title>",
         
     | 
| 
      
 57 
     | 
    
         
            +
                    "<!--Publication details-->",
         
     | 
| 
      
 58 
     | 
    
         
            +
                    '<published year="2024"></published>',
         
     | 
| 
      
 59 
     | 
    
         
            +
                    "<![CDATA[<custom>metadata</custom>]]>",
         
     | 
| 
      
 60 
     | 
    
         
            +
                    "</book>"
         
     | 
| 
      
 61 
     | 
    
         
            +
                  )
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
              describe "Direct document manipulation" do
         
     | 
| 
       26 
66 
     | 
    
         
             
                it "builds document with all features" do
         
     | 
| 
       27 
67 
     | 
    
         
             
                  doc = Moxml.new.create_document
         
     | 
| 
       28 
68 
     | 
    
         | 
| 
         @@ -38,10 +78,12 @@ RSpec.shared_examples "README Examples" do 
     | 
|
| 
       38 
78 
     | 
    
         
             
                  # Add books
         
     | 
| 
       39 
79 
     | 
    
         
             
                  %w[Ruby XML].each do |title|
         
     | 
| 
       40 
80 
     | 
    
         
             
                    book = doc.create_element("book")
         
     | 
| 
      
 81 
     | 
    
         
            +
                    book["id"] = "b1-#{title}"
         
     | 
| 
       41 
82 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                    # Add  
     | 
| 
      
 83 
     | 
    
         
            +
                    # Add mixed content
         
     | 
| 
      
 84 
     | 
    
         
            +
                    book.add_child(doc.create_comment("Book details"))
         
     | 
| 
       43 
85 
     | 
    
         
             
                    dc_title = doc.create_element("dc:title")
         
     | 
| 
       44 
     | 
    
         
            -
                    dc_title. 
     | 
| 
      
 86 
     | 
    
         
            +
                    dc_title.text = title
         
     | 
| 
       45 
87 
     | 
    
         
             
                    book.add_child(dc_title)
         
     | 
| 
       46 
88 
     | 
    
         | 
| 
       47 
89 
     | 
    
         
             
                    # Add description
         
     | 
| 
         @@ -52,13 +94,16 @@ RSpec.shared_examples "README Examples" do 
     | 
|
| 
       52 
94 
     | 
    
         
             
                    root.add_child(book)
         
     | 
| 
       53 
95 
     | 
    
         
             
                  end
         
     | 
| 
       54 
96 
     | 
    
         | 
| 
       55 
     | 
    
         
            -
                   
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
             
     | 
| 
      
 97 
     | 
    
         
            +
                  expect(doc.to_xml).to include(
         
     | 
| 
      
 98 
     | 
    
         
            +
                    '<?xml version="1.0" encoding="UTF-8"?>',
         
     | 
| 
      
 99 
     | 
    
         
            +
                    '<library xmlns="http://example.org/library" xmlns:dc="http://purl.org/dc/elements/1.1/">',
         
     | 
| 
      
 100 
     | 
    
         
            +
                    '<book id="b1-Ruby">',
         
     | 
| 
      
 101 
     | 
    
         
            +
                    "<!--Book details-->",
         
     | 
| 
      
 102 
     | 
    
         
            +
                    "<dc:title>Ruby</dc:title>",
         
     | 
| 
      
 103 
     | 
    
         
            +
                    "<![CDATA[About Ruby...]]>",
         
     | 
| 
      
 104 
     | 
    
         
            +
                    "<dc:title>XML</dc:title>",
         
     | 
| 
      
 105 
     | 
    
         
            +
                    "<![CDATA[About XML...]]>"
         
     | 
| 
      
 106 
     | 
    
         
            +
                  )
         
     | 
| 
       62 
107 
     | 
    
         
             
                end
         
     | 
| 
       63 
108 
     | 
    
         
             
              end
         
     | 
| 
       64 
109 
     | 
    
         | 
| 
         @@ -70,6 +115,18 @@ RSpec.shared_examples "README Examples" do 
     | 
|
| 
       70 
115 
     | 
    
         
             
                    context.parse("<invalid>")
         
     | 
| 
       71 
116 
     | 
    
         
             
                  end.to raise_error(Moxml::ParseError)
         
     | 
| 
       72 
117 
     | 
    
         | 
| 
      
 118 
     | 
    
         
            +
                  expect do
         
     | 
| 
      
 119 
     | 
    
         
            +
                    doc = context.parse("<root/>")
         
     | 
| 
      
 120 
     | 
    
         
            +
                    root = doc.root
         
     | 
| 
      
 121 
     | 
    
         
            +
                    root.add_namespace("n", "wrong.url")
         
     | 
| 
      
 122 
     | 
    
         
            +
                  end.to raise_error(Moxml::NamespaceError)
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
                  expect do
         
     | 
| 
      
 125 
     | 
    
         
            +
                    doc = context.parse("<root/>")
         
     | 
| 
      
 126 
     | 
    
         
            +
                    element = doc.create_element("wrong,name")
         
     | 
| 
      
 127 
     | 
    
         
            +
                    doc.add_child(element)
         
     | 
| 
      
 128 
     | 
    
         
            +
                  end.to raise_error(Moxml::ValidationError)
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
       73 
130 
     | 
    
         
             
                  doc = context.parse("<root/>")
         
     | 
| 
       74 
131 
     | 
    
         
             
                  expect do
         
     | 
| 
       75 
132 
     | 
    
         
             
                    doc.xpath("///")
         
     | 
| 
         @@ -111,7 +111,7 @@ RSpec.shared_examples "Moxml Integration" do 
     | 
|
| 
       111 
111 
     | 
    
         
             
                  # Move nodes
         
     | 
| 
       112 
112 
     | 
    
         
             
                  b_node = doc.at_xpath("//b")
         
     | 
| 
       113 
113 
     | 
    
         
             
                  a_node = doc.at_xpath("//a")
         
     | 
| 
       114 
     | 
    
         
            -
                   
     | 
| 
      
 114 
     | 
    
         
            +
                  a_node.add_previous_sibling(b_node)
         
     | 
| 
       115 
115 
     | 
    
         | 
| 
       116 
116 
     | 
    
         
             
                  # Add nodes
         
     | 
| 
       117 
117 
     | 
    
         
             
                  c_node = doc.create_element("c")
         
     | 
| 
         @@ -125,7 +125,7 @@ RSpec.shared_examples "Moxml Integration" do 
     | 
|
| 
       125 
125 
     | 
    
         
             
                  b_node.add_child(doc.create_comment(" comment "))
         
     | 
| 
       126 
126 
     | 
    
         
             
                  b_node.add_child(doc.create_cdata("<tag>"))
         
     | 
| 
       127 
127 
     | 
    
         | 
| 
       128 
     | 
    
         
            -
                  expect(doc.root.children.map(&:name)).to eq(%w[ 
     | 
| 
      
 128 
     | 
    
         
            +
                  expect(doc.root.children.map(&:name)).to eq(%w[b c a])
         
     | 
| 
       129 
129 
     | 
    
         
             
                  expect(doc.to_xml).to include(
         
     | 
| 
       130 
130 
     | 
    
         
             
                    '<root id="main">',
         
     | 
| 
       131 
131 
     | 
    
         
             
                    "<b>2<!-- comment --><![CDATA[<tag>]]></b>"
         
     | 
| 
         @@ -1,5 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            # This test works directly with native nodes which looks quite strange
         
     | 
| 
      
 4 
     | 
    
         
            +
            # A better way is to run it through Moxml wrappers
         
     | 
| 
       3 
5 
     | 
    
         
             
            RSpec.shared_examples "xml adapter" do
         
     | 
| 
       4 
6 
     | 
    
         
             
              let(:xml) do
         
     | 
| 
       5 
7 
     | 
    
         
             
                <<~XML
         
     | 
| 
         @@ -80,7 +82,7 @@ RSpec.shared_examples "xml adapter" do 
     | 
|
| 
       80 
82 
     | 
    
         
             
                  expect(children.length).to eq(3)
         
     | 
| 
       81 
83 
     | 
    
         
             
                end
         
     | 
| 
       82 
84 
     | 
    
         | 
| 
       83 
     | 
    
         
            -
                it "gets siblings" 
     | 
| 
      
 85 
     | 
    
         
            +
                it "gets siblings" do
         
     | 
| 
       84 
86 
     | 
    
         
             
                  children = described_class.children(root)
         
     | 
| 
       85 
87 
     | 
    
         
             
                  first = children[0]
         
     | 
| 
       86 
88 
     | 
    
         
             
                  second = children[1]
         
     | 
| 
         @@ -97,13 +99,16 @@ RSpec.shared_examples "xml adapter" do 
     | 
|
| 
       97 
99 
     | 
    
         | 
| 
       98 
100 
     | 
    
         
             
                it "adds text child" do
         
     | 
| 
       99 
101 
     | 
    
         
             
                  described_class.add_child(root, "text")
         
     | 
| 
       100 
     | 
    
         
            -
                   
     | 
| 
      
 102 
     | 
    
         
            +
                  # a workaround for Rexml until we convert tests to work with Moxml wrappers
         
     | 
| 
      
 103 
     | 
    
         
            +
                  last_child = described_class.children(root).last
         
     | 
| 
      
 104 
     | 
    
         
            +
                  last_text = last_child.respond_to?(:text) ? last_child.text : last_child.to_s
         
     | 
| 
      
 105 
     | 
    
         
            +
                  expect(last_text).to eq("text")
         
     | 
| 
       101 
106 
     | 
    
         
             
                end
         
     | 
| 
       102 
107 
     | 
    
         
             
              end
         
     | 
| 
       103 
108 
     | 
    
         | 
| 
       104 
109 
     | 
    
         
             
              describe "attributes" do
         
     | 
| 
       105 
     | 
    
         
            -
                let(:doc) { described_class.parse(xml) }
         
     | 
| 
       106 
     | 
    
         
            -
                let(:element) { described_class.children(described_class.root(doc 
     | 
| 
      
 110 
     | 
    
         
            +
                let(:doc) { described_class.parse(xml).native }
         
     | 
| 
      
 111 
     | 
    
         
            +
                let(:element) { described_class.children(described_class.root(doc)).first }
         
     | 
| 
       107 
112 
     | 
    
         | 
| 
       108 
113 
     | 
    
         
             
                it "gets attributes" do
         
     | 
| 
       109 
114 
     | 
    
         
             
                  attrs = described_class.attributes(element)
         
     | 
| 
         @@ -123,7 +128,9 @@ RSpec.shared_examples "xml adapter" do 
     | 
|
| 
       123 
128 
     | 
    
         | 
| 
       124 
129 
     | 
    
         
             
                it "handles special characters in attributes" do
         
     | 
| 
       125 
130 
     | 
    
         
             
                  described_class.set_attribute(element, "special", '< > & " \'')
         
     | 
| 
       126 
     | 
    
         
            -
                   
     | 
| 
      
 131 
     | 
    
         
            +
                  # a workaround for Rexml until we convert tests to work with Moxml wrappers
         
     | 
| 
      
 132 
     | 
    
         
            +
                  attr = described_class.get_attribute(element, "special")
         
     | 
| 
      
 133 
     | 
    
         
            +
                  value = attr.respond_to?(:to_xml) ? attr&.to_xml : attr.to_s
         
     | 
| 
       127 
134 
     | 
    
         
             
                  expect(value).to match(/< > & ("|") ('|')/)
         
     | 
| 
       128 
135 
     | 
    
         
             
                end
         
     | 
| 
       129 
136 
     | 
    
         
             
              end
         
     | 
| 
         @@ -156,7 +163,10 @@ RSpec.shared_examples "xml adapter" do 
     | 
|
| 
       156 
163 
     | 
    
         
             
                  expect(result).to include("</root>")
         
     | 
| 
       157 
164 
     | 
    
         
             
                end
         
     | 
| 
       158 
165 
     | 
    
         | 
| 
       159 
     | 
    
         
            -
                it "respects indentation settings" 
     | 
| 
      
 166 
     | 
    
         
            +
                it "respects indentation settings" do
         
     | 
| 
      
 167 
     | 
    
         
            +
                  pending("Oga does not support indentation settings") if described_class.name.include?("Oga")
         
     | 
| 
      
 168 
     | 
    
         
            +
                  pending("Postponed for Rexml till better times") if described_class.name.include?("Rexml")
         
     | 
| 
      
 169 
     | 
    
         
            +
             
     | 
| 
       160 
170 
     | 
    
         
             
                  unindented = described_class.serialize(doc, indent: 0)
         
     | 
| 
       161 
171 
     | 
    
         
             
                  indented = described_class.serialize(doc, indent: 2)
         
     | 
| 
       162 
172 
     | 
    
         | 
| 
         @@ -176,7 +186,7 @@ RSpec.shared_examples "xml adapter" do 
     | 
|
| 
       176 
186 
     | 
    
         
             
              end
         
     | 
| 
       177 
187 
     | 
    
         | 
| 
       178 
188 
     | 
    
         
             
              describe "xpath" do
         
     | 
| 
       179 
     | 
    
         
            -
                let(:doc) { described_class.parse(xml) }
         
     | 
| 
      
 189 
     | 
    
         
            +
                let(:doc) { described_class.parse(xml).native }
         
     | 
| 
       180 
190 
     | 
    
         | 
| 
       181 
191 
     | 
    
         
             
                it "finds nodes by xpath" do
         
     | 
| 
       182 
192 
     | 
    
         
             
                  nodes = described_class.xpath(doc, "//xmlns:child")
         
     | 
| 
         @@ -188,4 +198,156 @@ RSpec.shared_examples "xml adapter" do 
     | 
|
| 
       188 
198 
     | 
    
         
             
                  expect(described_class.get_attribute_value(node, "id")).to eq("1")
         
     | 
| 
       189 
199 
     | 
    
         
             
                end
         
     | 
| 
       190 
200 
     | 
    
         
             
              end
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
              describe "namespace handling" do
         
     | 
| 
      
 203 
     | 
    
         
            +
                context "case 1" do
         
     | 
| 
      
 204 
     | 
    
         
            +
                  let(:xml) do
         
     | 
| 
      
 205 
     | 
    
         
            +
                    <<~XML
         
     | 
| 
      
 206 
     | 
    
         
            +
                      <?xml version="1.0" encoding="UTF-8"?>
         
     | 
| 
      
 207 
     | 
    
         
            +
                      <svg xmlns="http://www.w3.org/2000/svg"
         
     | 
| 
      
 208 
     | 
    
         
            +
                           xmlns:xlink="http://www.w3.org/1999/xlink"
         
     | 
| 
      
 209 
     | 
    
         
            +
                           width="100" height="100">
         
     | 
| 
      
 210 
     | 
    
         
            +
                        <defs>
         
     | 
| 
      
 211 
     | 
    
         
            +
                          <circle id="myCircle" cx="50" cy="50" r="40"/>
         
     | 
| 
      
 212 
     | 
    
         
            +
                        </defs>
         
     | 
| 
      
 213 
     | 
    
         
            +
                        <use xlink:href="#myCircle" fill="red"/>
         
     | 
| 
      
 214 
     | 
    
         
            +
                        <text x="50" y="50" text-anchor="middle">SVG</text>
         
     | 
| 
      
 215 
     | 
    
         
            +
                      </svg>
         
     | 
| 
      
 216 
     | 
    
         
            +
                    XML
         
     | 
| 
      
 217 
     | 
    
         
            +
                  end
         
     | 
| 
      
 218 
     | 
    
         
            +
             
     | 
| 
      
 219 
     | 
    
         
            +
                  it "preserves and correctly handles multiple namespaces" do
         
     | 
| 
      
 220 
     | 
    
         
            +
                    pending("Rexml does not respect ZPath namespaces") if described_class.name.include?("Rexml")
         
     | 
| 
      
 221 
     | 
    
         
            +
                    # Parse original XML
         
     | 
| 
      
 222 
     | 
    
         
            +
                    doc = described_class.parse(xml).native
         
     | 
| 
      
 223 
     | 
    
         
            +
             
     | 
| 
      
 224 
     | 
    
         
            +
                    # Test namespace preservation in serialization
         
     | 
| 
      
 225 
     | 
    
         
            +
                    result = described_class.serialize(doc)
         
     | 
| 
      
 226 
     | 
    
         
            +
                    expect(result).to include('xmlns="http://www.w3.org/2000/svg"')
         
     | 
| 
      
 227 
     | 
    
         
            +
                    expect(result).to include('xmlns:xlink="http://www.w3.org/1999/xlink"')
         
     | 
| 
      
 228 
     | 
    
         
            +
             
     | 
| 
      
 229 
     | 
    
         
            +
                    # Test xpath with namespaces
         
     | 
| 
      
 230 
     | 
    
         
            +
                    namespaces = {
         
     | 
| 
      
 231 
     | 
    
         
            +
                      "svg" => "http://www.w3.org/2000/svg",
         
     | 
| 
      
 232 
     | 
    
         
            +
                      "xlink" => "http://www.w3.org/1999/xlink"
         
     | 
| 
      
 233 
     | 
    
         
            +
                    }
         
     | 
| 
      
 234 
     | 
    
         
            +
             
     | 
| 
      
 235 
     | 
    
         
            +
                    # Find use element and verify xlink:href attribute
         
     | 
| 
      
 236 
     | 
    
         
            +
                    use_elem = described_class.at_xpath(doc, "//svg:use", namespaces)
         
     | 
| 
      
 237 
     | 
    
         
            +
                    expect(use_elem).not_to be_nil
         
     | 
| 
      
 238 
     | 
    
         
            +
                    expect(described_class.get_attribute_value(use_elem, "xlink:href")).to eq("#myCircle")
         
     | 
| 
      
 239 
     | 
    
         
            +
             
     | 
| 
      
 240 
     | 
    
         
            +
                    # Verify circle element exists in defs
         
     | 
| 
      
 241 
     | 
    
         
            +
                    circle = described_class.at_xpath(doc, "//svg:defs/svg:circle", namespaces)
         
     | 
| 
      
 242 
     | 
    
         
            +
                    expect(circle).not_to be_nil
         
     | 
| 
      
 243 
     | 
    
         
            +
                    expect(described_class.get_attribute_value(circle, "id")).to eq("myCircle")
         
     | 
| 
      
 244 
     | 
    
         
            +
             
     | 
| 
      
 245 
     | 
    
         
            +
                    # Test default SVG namespace
         
     | 
| 
      
 246 
     | 
    
         
            +
                    text = described_class.at_xpath(doc, "//svg:text", namespaces)
         
     | 
| 
      
 247 
     | 
    
         
            +
                    expect(described_class.text_content(text)).to eq("SVG")
         
     | 
| 
      
 248 
     | 
    
         
            +
                  end
         
     | 
| 
      
 249 
     | 
    
         
            +
                end
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
                context "case 2" do
         
     | 
| 
      
 252 
     | 
    
         
            +
                  let(:xml) do
         
     | 
| 
      
 253 
     | 
    
         
            +
                    <<~XML
         
     | 
| 
      
 254 
     | 
    
         
            +
                      <?xml version="1.0" encoding="UTF-8"?>
         
     | 
| 
      
 255 
     | 
    
         
            +
                      <rss version="2.0"#{" "}
         
     | 
| 
      
 256 
     | 
    
         
            +
                        xmlns:atom="http://www.w3.org/2005/Atom"
         
     | 
| 
      
 257 
     | 
    
         
            +
                        xmlns:dc="http://purl.org/dc/elements/1.1/"
         
     | 
| 
      
 258 
     | 
    
         
            +
                        xmlns:content="http://purl.org/rss/1.0/modules/content/">
         
     | 
| 
      
 259 
     | 
    
         
            +
                        <channel>
         
     | 
| 
      
 260 
     | 
    
         
            +
                          <title>Example RSS Feed</title>
         
     | 
| 
      
 261 
     | 
    
         
            +
                          <atom:link href="http://example.com/feed" rel="self"/>
         
     | 
| 
      
 262 
     | 
    
         
            +
                          <item>
         
     | 
| 
      
 263 
     | 
    
         
            +
                            <title>Example Post</title>
         
     | 
| 
      
 264 
     | 
    
         
            +
                            <dc:creator>John Doe</dc:creator>
         
     | 
| 
      
 265 
     | 
    
         
            +
                            <content:encoded><![CDATA[<p>Post content</p>]]></content:encoded>
         
     | 
| 
      
 266 
     | 
    
         
            +
                          </item>
         
     | 
| 
      
 267 
     | 
    
         
            +
                        </channel>
         
     | 
| 
      
 268 
     | 
    
         
            +
                      </rss>
         
     | 
| 
      
 269 
     | 
    
         
            +
                    XML
         
     | 
| 
      
 270 
     | 
    
         
            +
                  end
         
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
      
 272 
     | 
    
         
            +
                  it "preserves and correctly handles multiple namespaces" do
         
     | 
| 
      
 273 
     | 
    
         
            +
                    # Parse original XML
         
     | 
| 
      
 274 
     | 
    
         
            +
                    doc = described_class.parse(xml).native
         
     | 
| 
      
 275 
     | 
    
         
            +
             
     | 
| 
      
 276 
     | 
    
         
            +
                    # Test namespace preservation in serialization
         
     | 
| 
      
 277 
     | 
    
         
            +
                    result = described_class.serialize(doc)
         
     | 
| 
      
 278 
     | 
    
         
            +
                    expect(result).to include('xmlns:atom="http://www.w3.org/2005/Atom"')
         
     | 
| 
      
 279 
     | 
    
         
            +
                    expect(result).to include('xmlns:dc="http://purl.org/dc/elements/1.1/"')
         
     | 
| 
      
 280 
     | 
    
         
            +
                    expect(result).to include('xmlns:content="http://purl.org/rss/1.0/modules/content/"')
         
     | 
| 
      
 281 
     | 
    
         
            +
             
     | 
| 
      
 282 
     | 
    
         
            +
                    # Test xpath with namespaces
         
     | 
| 
      
 283 
     | 
    
         
            +
                    namespaces = {
         
     | 
| 
      
 284 
     | 
    
         
            +
                      "atom" => "http://www.w3.org/2005/Atom",
         
     | 
| 
      
 285 
     | 
    
         
            +
                      "dc" => "http://purl.org/dc/elements/1.1/",
         
     | 
| 
      
 286 
     | 
    
         
            +
                      "content" => "http://purl.org/rss/1.0/modules/content/"
         
     | 
| 
      
 287 
     | 
    
         
            +
                    }
         
     | 
| 
      
 288 
     | 
    
         
            +
             
     | 
| 
      
 289 
     | 
    
         
            +
                    # Find creator using namespaced xpath
         
     | 
| 
      
 290 
     | 
    
         
            +
                    creator = described_class.at_xpath(doc, "//dc:creator", namespaces)
         
     | 
| 
      
 291 
     | 
    
         
            +
                    expect(described_class.text_content(creator)).to eq("John Doe")
         
     | 
| 
      
 292 
     | 
    
         
            +
             
     | 
| 
      
 293 
     | 
    
         
            +
                    # Verify atom:link exists
         
     | 
| 
      
 294 
     | 
    
         
            +
                    link = described_class.at_xpath(doc, "//atom:link", namespaces)
         
     | 
| 
      
 295 
     | 
    
         
            +
                    expect(link).not_to be_nil
         
     | 
| 
      
 296 
     | 
    
         
            +
                    expect(described_class.get_attribute_value(link, "href")).to eq("http://example.com/feed")
         
     | 
| 
      
 297 
     | 
    
         
            +
             
     | 
| 
      
 298 
     | 
    
         
            +
                    # Verify CDATA in content:encoded
         
     | 
| 
      
 299 
     | 
    
         
            +
                    content = described_class.at_xpath(doc, "//content:encoded", namespaces)
         
     | 
| 
      
 300 
     | 
    
         
            +
                    expect(described_class.text_content(content)).to eq("<p>Post content</p>")
         
     | 
| 
      
 301 
     | 
    
         
            +
                  end
         
     | 
| 
      
 302 
     | 
    
         
            +
                end
         
     | 
| 
      
 303 
     | 
    
         
            +
             
     | 
| 
      
 304 
     | 
    
         
            +
                context "case 3" do
         
     | 
| 
      
 305 
     | 
    
         
            +
                  let(:xml) do
         
     | 
| 
      
 306 
     | 
    
         
            +
                    <<~XML
         
     | 
| 
      
 307 
     | 
    
         
            +
                      <?xml version="1.0" encoding="UTF-8"?>
         
     | 
| 
      
 308 
     | 
    
         
            +
                      <soap:Envelope#{" "}
         
     | 
| 
      
 309 
     | 
    
         
            +
                        xmlns:soap="http://www.w3.org/2003/05/soap-envelope"
         
     | 
| 
      
 310 
     | 
    
         
            +
                        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         
     | 
| 
      
 311 
     | 
    
         
            +
                        xmlns:ns="urn:example:namespace">
         
     | 
| 
      
 312 
     | 
    
         
            +
                        <soap:Header>
         
     | 
| 
      
 313 
     | 
    
         
            +
                          <ns:SessionId>12345</ns:SessionId>
         
     | 
| 
      
 314 
     | 
    
         
            +
                        </soap:Header>
         
     | 
| 
      
 315 
     | 
    
         
            +
                        <soap:Body>
         
     | 
| 
      
 316 
     | 
    
         
            +
                          <ns:GetUserRequest>
         
     | 
| 
      
 317 
     | 
    
         
            +
                            <ns:UserId xsi:type="xsi:string">user123</ns:UserId>
         
     | 
| 
      
 318 
     | 
    
         
            +
                          </ns:GetUserRequest>
         
     | 
| 
      
 319 
     | 
    
         
            +
                        </soap:Body>
         
     | 
| 
      
 320 
     | 
    
         
            +
                      </soap:Envelope>
         
     | 
| 
      
 321 
     | 
    
         
            +
                    XML
         
     | 
| 
      
 322 
     | 
    
         
            +
                  end
         
     | 
| 
      
 323 
     | 
    
         
            +
             
     | 
| 
      
 324 
     | 
    
         
            +
                  it "preserves and correctly handles multiple namespaces" do
         
     | 
| 
      
 325 
     | 
    
         
            +
                    # Parse original XML
         
     | 
| 
      
 326 
     | 
    
         
            +
                    doc = described_class.parse(xml).native
         
     | 
| 
      
 327 
     | 
    
         
            +
             
     | 
| 
      
 328 
     | 
    
         
            +
                    # Test namespace preservation in serialization
         
     | 
| 
      
 329 
     | 
    
         
            +
                    result = described_class.serialize(doc)
         
     | 
| 
      
 330 
     | 
    
         
            +
                    expect(result).to include('xmlns:soap="http://www.w3.org/2003/05/soap-envelope"')
         
     | 
| 
      
 331 
     | 
    
         
            +
                    expect(result).to include('xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"')
         
     | 
| 
      
 332 
     | 
    
         
            +
                    expect(result).to include('xmlns:ns="urn:example:namespace"')
         
     | 
| 
      
 333 
     | 
    
         
            +
             
     | 
| 
      
 334 
     | 
    
         
            +
                    # Test xpath with namespaces
         
     | 
| 
      
 335 
     | 
    
         
            +
                    namespaces = {
         
     | 
| 
      
 336 
     | 
    
         
            +
                      "soap" => "http://www.w3.org/2003/05/soap-envelope",
         
     | 
| 
      
 337 
     | 
    
         
            +
                      "ns" => "urn:example:namespace"
         
     | 
| 
      
 338 
     | 
    
         
            +
                    }
         
     | 
| 
      
 339 
     | 
    
         
            +
             
     | 
| 
      
 340 
     | 
    
         
            +
                    # Find user ID using namespaced xpath
         
     | 
| 
      
 341 
     | 
    
         
            +
                    user_id = described_class.at_xpath(doc, "//ns:UserId", namespaces)
         
     | 
| 
      
 342 
     | 
    
         
            +
                    expect(described_class.text_content(user_id)).to eq("user123")
         
     | 
| 
      
 343 
     | 
    
         
            +
             
     | 
| 
      
 344 
     | 
    
         
            +
                    # Verify soap:Body exists
         
     | 
| 
      
 345 
     | 
    
         
            +
                    body = described_class.at_xpath(doc, "//soap:Body", namespaces)
         
     | 
| 
      
 346 
     | 
    
         
            +
                    expect(body).not_to be_nil
         
     | 
| 
      
 347 
     | 
    
         
            +
             
     | 
| 
      
 348 
     | 
    
         
            +
                    # Verify attribute with namespace
         
     | 
| 
      
 349 
     | 
    
         
            +
                    expect(described_class.get_attribute_value(user_id, "xsi:type")).to eq("xsi:string")
         
     | 
| 
      
 350 
     | 
    
         
            +
                  end
         
     | 
| 
      
 351 
     | 
    
         
            +
                end
         
     | 
| 
      
 352 
     | 
    
         
            +
              end
         
     | 
| 
       191 
353 
     | 
    
         
             
            end
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: moxml
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 0.1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 0.1.4
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Ribose Inc.
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire:
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: exe
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date: 2025- 
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2025-05-12 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies: []
         
     | 
| 
       13 
13 
     | 
    
         
             
            description: 'Moxml is a unified XML manipulation library that provides a common API.
         
     | 
| 
       14 
14 
     | 
    
         | 
| 
         @@ -27,6 +27,7 @@ files: 
     | 
|
| 
       27 
27 
     | 
    
         
             
            - ".rubocop_todo.yml"
         
     | 
| 
       28 
28 
     | 
    
         
             
            - ".ruby-version"
         
     | 
| 
       29 
29 
     | 
    
         
             
            - Gemfile
         
     | 
| 
      
 30 
     | 
    
         
            +
            - LICENSE.md
         
     | 
| 
       30 
31 
     | 
    
         
             
            - README.adoc
         
     | 
| 
       31 
32 
     | 
    
         
             
            - Rakefile
         
     | 
| 
       32 
33 
     | 
    
         
             
            - bin/console
         
     | 
| 
         @@ -36,9 +37,11 @@ files: 
     | 
|
| 
       36 
37 
     | 
    
         
             
            - lib/moxml/adapter/base.rb
         
     | 
| 
       37 
38 
     | 
    
         
             
            - lib/moxml/adapter/customized_oga/xml_declaration.rb
         
     | 
| 
       38 
39 
     | 
    
         
             
            - lib/moxml/adapter/customized_oga/xml_generator.rb
         
     | 
| 
      
 40 
     | 
    
         
            +
            - lib/moxml/adapter/customized_rexml/formatter.rb
         
     | 
| 
       39 
41 
     | 
    
         
             
            - lib/moxml/adapter/nokogiri.rb
         
     | 
| 
       40 
42 
     | 
    
         
             
            - lib/moxml/adapter/oga.rb
         
     | 
| 
       41 
43 
     | 
    
         
             
            - lib/moxml/adapter/ox.rb
         
     | 
| 
      
 44 
     | 
    
         
            +
            - lib/moxml/adapter/rexml.rb
         
     | 
| 
       42 
45 
     | 
    
         
             
            - lib/moxml/attribute.rb
         
     | 
| 
       43 
46 
     | 
    
         
             
            - lib/moxml/builder.rb
         
     | 
| 
       44 
47 
     | 
    
         
             
            - lib/moxml/cdata.rb
         
     | 
| 
         @@ -64,6 +67,7 @@ files: 
     | 
|
| 
       64 
67 
     | 
    
         
             
            - spec/moxml/adapter/nokogiri_spec.rb
         
     | 
| 
       65 
68 
     | 
    
         
             
            - spec/moxml/adapter/oga_spec.rb
         
     | 
| 
       66 
69 
     | 
    
         
             
            - spec/moxml/adapter/ox_spec.rb
         
     | 
| 
      
 70 
     | 
    
         
            +
            - spec/moxml/adapter/rexml_spec.rb
         
     | 
| 
       67 
71 
     | 
    
         
             
            - spec/moxml/all_with_adapters_spec.rb
         
     | 
| 
       68 
72 
     | 
    
         
             
            - spec/moxml/config_spec.rb
         
     | 
| 
       69 
73 
     | 
    
         
             
            - spec/moxml/error_spec.rb
         
     | 
| 
         @@ -116,7 +120,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement 
     | 
|
| 
       116 
120 
     | 
    
         
             
                - !ruby/object:Gem::Version
         
     | 
| 
       117 
121 
     | 
    
         
             
                  version: '0'
         
     | 
| 
       118 
122 
     | 
    
         
             
            requirements: []
         
     | 
| 
       119 
     | 
    
         
            -
            rubygems_version: 3. 
     | 
| 
      
 123 
     | 
    
         
            +
            rubygems_version: 3.5.22
         
     | 
| 
       120 
124 
     | 
    
         
             
            signing_key:
         
     | 
| 
       121 
125 
     | 
    
         
             
            specification_version: 4
         
     | 
| 
       122 
126 
     | 
    
         
             
            summary: Unified XML manipulation library
         
     |