odeac

odeac

I have to parse an XML with the following structure:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <root >
        <node id="1"/>
        <node id="2"/>
    </root>

And I have tried the following approache based on xpath:


  def parse_root(root_xml) do
    root_xml
    |> xpath(~x"//root",
      nodes: ~x"./node"l |> transform_by(&parse_node/1)
    )
  end

  def parse_node(node_xml) do
    node_xml
    |> xpath(~x"node", id: ~x"@id")
  end

  test "parse root" do
    xml = """
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <root >
        <node id="1"/>
        <node id="2"/>
    </root>
    """

    assert %{
             nodes: [
               %{id: "id1"},
               %{id: "id2"}
             ]
           } == parse_root(xml)
  end

This fails with the following runtime error:

  2) test parse root (TestSweet)
     test/sweet_test.exs:172
     ** (ArgumentError) errors were found at the given arguments:

       * 1st argument: not a bitstring

     code: } == parse_root(xml)
     stacktrace:
       :erlang.byte_size({:xmlElement, :node, :node, [], {:xmlNamespace, [], []}, [root: 1], 2, [{:xmlAttribute, :id, [], [], [], [node: 2, root: 1], 1, [], ~c"1", false}], [], [], ~c"/Users/ovi/work/eb/playground", :undeclared})
       (sweet_xml 0.7.4) lib/sweet_xml.ex:834: SweetXml.split_last_whitespace/1
       (sweet_xml 0.7.4) lib/sweet_xml.ex:825: anonymous fn/2 in SweetXml.split_by_whitespace/1
       (elixir 1.15.7) lib/stream.ex:990: Stream.do_transform_user/6
       (sweet_xml 0.7.4) lib/sweet_xml.ex:788: anonymous fn/4 in SweetXml.continuation_opts/2
       (xmerl 1.3.31) xmerl_scan.erl:571: :xmerl_scan.scan_document/2
       (xmerl 1.3.31) xmerl_scan.erl:294: :xmerl_scan.string/2
       (sweet_xml 0.7.4) lib/sweet_xml.ex:296: SweetXml.do_parse/2
       (sweet_xml 0.7.4) lib/sweet_xml.ex:281: SweetXml.parse/2
       (sweet_xml 0.7.4) lib/sweet_xml.ex:610: SweetXml.xpath/3
       (sweet_xml 0.7.4) lib/sweet_xml.ex:642: SweetXml.xpath/3
       (sweet_xml 0.7.4) lib/sweet_xml.ex:737: anonymous fn/3 in SweetXml.xmap/3
       (elixir 1.15.7) lib/map.ex:957: Map.get_and_update/3
       (sweet_xml 0.7.4) lib/sweet_xml.ex:737: SweetXml.xmap/3
       test/sweet_test.exs:187: (test)

I also tried to parse the same XML using xmap as you can see below:

def parse_root2(root_xml) do
    root_xml
    |> xmap(~x"//root",
      nodes: [
        ~x"./node",
        id: ~x"@id"
      ]
    )
  end

  test "parse root 2" do
    xml = """
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <root >
        <node id="1"/>
        <node id="2"/>
    </root>
    """

    assert %{
             nodes: [
               %{id: "id1"},
               %{id: "id2"}
             ]
           } == parse_root2(xml)
  end

…and it fails with the following error:

  1) test parse root 2 (TestSweet)
     test/sweet_test.exs:200
     ** (FunctionClauseError) no function clause matching in SweetXml.xmap/3

     The following arguments were given to SweetXml.xmap/3:

         # 1
         "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n\n<root >\n    <node id=\"1\"/>\n    <node id=\"2\"/>\n</root>\n"

         # 2
         %SweetXpath{path: ~c"//root", is_value: true, is_list: false, is_keyword: false, is_optional: false, cast_to: false, transform_fun: &SweetXpath.Priv.self_val/1, namespaces: []}

         # 3
         [nodes: [%SweetXpath{path: ~c"./node", is_value: true, is_list: false, is_keyword: false, is_optional: false, cast_to: false, transform_fun: &SweetXpath.Priv.self_val/1, namespaces: []}, {:id, %SweetXpath{path: ~c"@id", is_value: true, is_list: false, is_keyword: false, is_optional: false, cast_to: false, transform_fun: &SweetXpath.Priv.self_val/1, namespaces: []}}]]

     Attempted function clauses (showing 6 out of 6):

         def xmap(nil, _, %{is_optional: true})
         def xmap(parent, [], atom) when is_atom(atom)
         def xmap(_, [], %{is_keyword: false})
         def xmap(_, [], %{is_keyword: true})
         def xmap(parent, [{label, spec} | tail], is_keyword) when is_list(spec)
         def xmap(parent, [{label, sweet_xpath} | tail], is_keyword)

     code: } == parse_root2(xml)
     stacktrace:
       (sweet_xml 0.7.4) lib/sweet_xml.ex:721: SweetXml.xmap/3
       test/sweet_test.exs:215: (test)

Any suggestions will be highly appreciated.

Thanks in advance!

Showing Posts 1 to 2

Hermanverschooten

Hermanverschooten

I tried this in a livebook.

import SweetXml
xml = """
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>

    <root >
        <node id="1"/>
        <node id="2"/>
    </root>
"""

xml
|> xpath(~x"//root", nodes: [~x"./node"l, id: ~x"@id"i])

%{nodes: [%{id: 1}, %{id: 2}]}

xml
|> xpath(~x"//root", nodes: [~x"./node"l, id: ~x"@id"s |> transform_by(fn x -> "id" <> x end)])

%{nodes: [%{id: "id1"}, %{id: "id2"}]}
odeac

odeac OP

Sorry for the late reply. It works!

— All posts loaded —

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
mnkhod
So i have been using ash framework for a while and i love it. However currently the issue im having with ash framework is the error handl...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews