Created
March 4, 2025 19:03
-
-
Save ckampfe/b0089b046bc2041e521b842f7002d34a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?xml version="1.0" encoding="UTF-8"?> | |
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | |
<modelVersion>4.0.0</modelVersion> | |
<groupId>net.clojars.ckampfe</groupId> | |
<artifactId>fp</artifactId> | |
<version>0.1.0-SNAPSHOT</version> | |
<name>ckampfe/fp</name> | |
<description>FIXME: my new application.</description> | |
<url>https://github.com/ckampfe/fp</url> | |
<licenses> | |
<license> | |
<name>Eclipse Public License</name> | |
<url>http://www.eclipse.org/legal/epl-v10.html</url> | |
</license> | |
</licenses> | |
<developers> | |
<developer> | |
<name>Clark</name> | |
</developer> | |
</developers> | |
<scm> | |
<url>https://github.com/ckampfe/fp</url> | |
<connection>scm:git:git://github.com/ckampfe/fp.git</connection> | |
<developerConnection>scm:git:ssh://[email protected]/ckampfe/fp.git</developerConnection> | |
<tag>v0.1.0-SNAPSHOT</tag> | |
</scm> | |
<dependencies> | |
<dependency> | |
<groupId>org.clojure</groupId> | |
<artifactId>clojure</artifactId> | |
<version>1.11.1</version> | |
</dependency> | |
</dependencies> | |
<build> | |
<sourceDirectory>src</sourceDirectory> | |
</build> | |
<repositories> | |
<repository> | |
<id>clojars</id> | |
<url>https://repo.clojars.org/</url> | |
</repository> | |
<repository> | |
<id>sonatype</id> | |
<url>https://oss.sonatype.org/content/repositories/snapshots/</url> | |
</repository> | |
</repositories> | |
<distributionManagement> | |
<repository> | |
<id>clojars</id> | |
<name>Clojars repository</name> | |
<url>https://clojars.org/repo</url> | |
</repository> | |
</distributionManagement> | |
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule Saxml do | |
import Kernel, except: [get_in: 2, get_in: 1] | |
defmacro sigil_l(s, []) do | |
{:list, s} | |
end | |
defmacro get_in(m, [key]) do | |
case key do | |
# an attribute | |
"@" <> _rest -> | |
quote do | |
case unquote(m) do | |
%{unquote(key) => v} -> | |
v | |
_ -> | |
nil | |
end | |
end | |
# a "list" designator | |
{:sigil_l, _meta1, [{:<<>>, _meta2, [s]}, []]} -> | |
quote do | |
Enum.map(unquote(m), fn %{unquote(s) => %{"content" => v}} -> | |
v | |
end) | |
end | |
{variable_name, _meta, _} when is_atom(variable_name) -> | |
quote do | |
case unquote(m) do | |
%{^unquote(key) => %{"content" => v}} -> | |
v | |
_ -> | |
nil | |
end | |
end | |
# any normal element lookup | |
_k -> | |
quote do | |
case unquote(m) do | |
%{unquote(key) => %{"content" => v}} -> | |
v | |
_ -> | |
nil | |
end | |
end | |
end | |
end | |
defmacro get_in(m, [key, next_key | keys]) do | |
case key do | |
# an attribute | |
"@" <> _rest -> | |
quote do | |
case unquote(m) do | |
%{unquote(key) => v} -> | |
Saxml.get_in(v, unquote(keys)) | |
_ -> | |
nil | |
end | |
end | |
{variable_name, _meta, _} when is_atom(variable_name) -> | |
case next_key do | |
# the next key is an attribute | |
"@" <> _rest -> | |
quote do | |
case unquote(m) do | |
%{^unquote(key) => v} -> | |
Saxml.get_in(v, unquote([next_key | keys])) | |
_ -> | |
nil | |
end | |
end | |
# the next key is a list designator | |
{:sigil_l, _meta1, [{:<<>>, _meta2, [s]}, []]} -> | |
quote do | |
case unquote(m) do | |
%{^unquote(key) => l} when is_list(l) -> | |
Enum.map(l, fn %{"content" => %{unquote(s) => %{"content" => v}}} -> | |
v | |
end) | |
_ -> | |
nil | |
end | |
end | |
# the next key is a normal element lookup | |
_non_attribute -> | |
quote do | |
case unquote(m) do | |
%{^unquote(key) => %{"content" => content}} -> | |
Saxml.get_in(content, unquote([next_key | keys])) | |
_ -> | |
nil | |
end | |
end | |
end | |
# any normal element lookup | |
_key -> | |
case next_key do | |
# the next key is an attribute | |
"@" <> _rest -> | |
quote do | |
case unquote(m) do | |
%{unquote(key) => v} -> | |
Saxml.get_in(v, unquote([next_key | keys])) | |
_ -> | |
nil | |
end | |
end | |
# the next key is a list designator | |
{:sigil_l, _meta1, [{:<<>>, _meta2, [s]}, []]} -> | |
quote do | |
case unquote(m) do | |
%{unquote(key) => l} when is_list(l) -> | |
Enum.map(l, fn %{"content" => %{unquote(s) => %{"content" => v}}} -> | |
v | |
end) | |
_ -> | |
nil | |
end | |
end | |
# the next key is a normal element lookup | |
_non_attribute -> | |
quote do | |
case unquote(m) do | |
%{unquote(key) => %{"content" => content}} -> | |
Saxml.get_in(content, unquote([next_key | keys])) | |
_ -> | |
nil | |
end | |
end | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
defmodule SaxmlTest do | |
use ExUnit.Case | |
doctest Saxml | |
require Saxml | |
setup do | |
file = File.read!("pom.xml") | |
{:ok, m} = | |
SAXMap.from_string(file, ignore_attribute: {false, "@"}) | |
# |> IO.inspect() | |
[m: m] | |
end | |
test "greets the world", %{m: m} do | |
assert "http://maven.apache.org/POM/4.0.0" == | |
Saxml.get_in(m, ["project", "@xmlns"]) | |
assert "http://www.w3.org/2001/XMLSchema-instance" == | |
Saxml.get_in(m, ["project", "@xmlns:xsi"]) | |
assert "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" == | |
Saxml.get_in(m, ["project", "@xsi:schemaLocation"]) | |
assert "4.0.0" == Saxml.get_in(m, ["project", "modelVersion"]) | |
assert "net.clojars.ckampfe" == Saxml.get_in(m, ["project", "groupId"]) | |
assert "fp" == Saxml.get_in(m, ["project", "artifactId"]) | |
assert "0.1.0-SNAPSHOT" == Saxml.get_in(m, ["project", "version"]) | |
assert "ckampfe/fp" == Saxml.get_in(m, ["project", "name"]) | |
assert "FIXME: my new application." == Saxml.get_in(m, ["project", "description"]) | |
assert "https://github.com/ckampfe/fp" == Saxml.get_in(m, ["project", "url"]) | |
assert "Eclipse Public License" == Saxml.get_in(m, ["project", "licenses", "license", "name"]) | |
assert "http://www.eclipse.org/legal/epl-v10.html" == | |
Saxml.get_in(m, ["project", "licenses", "license", "url"]) | |
assert "Clark" == Saxml.get_in(m, ["project", "developers", "developer", "name"]) | |
assert "https://github.com/ckampfe/fp" == Saxml.get_in(m, ["project", "scm", "url"]) | |
assert "scm:git:git://github.com/ckampfe/fp.git" == | |
Saxml.get_in(m, ["project", "scm", "connection"]) | |
assert "scm:git:ssh://[email protected]/ckampfe/fp.git" == | |
Saxml.get_in(m, ["project", "scm", "developerConnection"]) | |
assert "v0.1.0-SNAPSHOT" == Saxml.get_in(m, ["project", "scm", "tag"]) | |
assert "org.clojure" == | |
Saxml.get_in(m, ["project", "dependencies", "dependency", "groupId"]) | |
assert "clojure" == | |
Saxml.get_in(m, ["project", "dependencies", "dependency", "artifactId"]) | |
assert "1.11.1" == | |
Saxml.get_in(m, ["project", "dependencies", "dependency", "version"]) | |
assert "src" == Saxml.get_in(m, ["project", "build", "sourceDirectory"]) | |
# assert [ | |
# %{ | |
# "id" => %{"content" => "clojars"}, | |
# "url" => %{"content" => "https://repo.clojars.org/"} | |
# }, | |
# %{ | |
# "id" => %{"content" => "sonatype"}, | |
# "url" => %{"content" => "https://oss.sonatype.org/content/repositories/snapshots/"} | |
# } | |
# ] == | |
# Saxml.get_in(m, ["project", "repositories", "repository"]) | |
assert "clojars" == Saxml.get_in(m, ["project", "distributionManagement", "repository", "id"]) | |
assert "Clojars repository" == | |
Saxml.get_in(m, ["project", "distributionManagement", "repository", "name"]) | |
assert "https://clojars.org/repo" == | |
Saxml.get_in(m, ["project", "distributionManagement", "repository", "url"]) | |
end | |
test "lists", %{m: m} do | |
assert [ | |
"clojars", | |
"sonatype" | |
] == | |
Saxml.get_in(m, ["project", "repositories", "repository", ~l"id"]) | |
assert [ | |
"https://repo.clojars.org/", | |
"https://oss.sonatype.org/content/repositories/snapshots/" | |
] == | |
Saxml.get_in(m, ["project", "repositories", "repository", ~l"url"]) | |
end | |
test "variables", %{m: m} do | |
version_element = "version" | |
assert "1.11.1" == | |
Saxml.get_in(m, ["project", "dependencies", "dependency", version_element]) | |
dependencies_element = "dependencies" | |
assert "1.11.1" == | |
Saxml.get_in(m, ["project", dependencies_element, "dependency", version_element]) | |
end | |
test "variables lists", %{m: m} do | |
respositories_tag = "repositories" | |
assert [ | |
"clojars", | |
"sonatype" | |
] == | |
Saxml.get_in(m, ["project", respositories_tag, "repository", ~l"id"]) | |
# this does not work, I do not know if it can be made to work, | |
# since the macro would need to be able to see through the variable, | |
# to see that it is a list designator | |
# | |
# id_tag = ~l"id" | |
# assert [ | |
# "clojars", | |
# "sonatype" | |
# ] == | |
# Saxml.get_in(m, ["project", respositories_tag, "repository", id_tag]) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment