AcuteML.aml_create
AcuteML.aml_parse
AcuteML.createnode
AcuteML.newTemplate
AcuteML.pprint
AcuteML.render2file
EzXML.parsehtml
EzXML.parsexml
EzXML.readhtml
EzXML.readxml
AcuteML.@aml
AcuteML.@aml
Main Macro and IO
AcuteML.@aml
— Macro@aml
Type Definition
Use @aml
macro to define a Julia type, and then the package automatically creates a xml or html associated with the defined type. The general syntax would look like this:
@aml mutable struct mybody "body"
myh1, "h1"
p::Vector{String}, "~"
end
You can also define the structs as parametric:
@aml mutable struct MyGeneralXML{T} "my-general-xml"
myfield::T, "~"
end
pxml_string = MyGeneralXML{String}(myfield = "a")
pprint(pxml_string)
pxml_vector = MyGeneralXML{Vector{String}}(myfield = ["b","c"])
pprint(pxml_vector)
Now, we go into the details:
Document Definition
- Use doc literal before the root name to define a HTML or XML document. For HTML documents root should always be "html".
@aml mutable struct Doc doc"xml_root"
# add fields (elements) here
end
@aml mutable struct Web doc"html"
# add fields (elements) here
end
Nodes (Elements) Definition
- Specify the html/xml name of struct as a string after the struct name (after a space)
@aml mutable struct Person "person"
# add fields (elements) here
end
- If the html/xml name is the same as struct name, you can use
"~"
instead
@aml mutable struct person "~"
# add fields (elements) here
end
Fields Names
- Sepecify the html/xml field name as a string in front of the field after
,
field, "study-field"
- If the html/xml name is the same as variable name, you can use
"~"
instead
age::UInt, "~"
The field names of a struct should not be the same as other defined types. This error happens when you use the same name of a type for a field name. For example, the follwing is an error:
@aml struct person "~"
name, "~"
end
@aml struct myxml doc"~"
person::person, "~"
end
Another example of this error:
@aml struct myxml doc"~"
Int, "myint"
end
However, you can choose any xml/html name. The xml/html name of the fields isn't related to the types defined in Julia. So the following is a valid syntax:
@aml struct myxml doc"~"
myint, "Int"
end
Attributes
- If the value is going to be an attribute put
att
before its name
id::Int64, att"~"
Default Value
- You can specify the default value for an argument by using
= defVal
syntax
GPA::Float64 = 4.5, "~"
Value Types
You can use Julia types or defined types for values. see and Supported Value Types Custom Value Types for more information.
- If you don't specify the type of a variable, it is considered to be string for aml manipulations:
field, "study-field"
However, for a high performance code specify String type (field::String, "study-field"
)
- For already
@aml
defined types, name should be the same as the defined type root name
university::University, "university"
- Table types are supported through PrettyTables.jl.
Value Checking
You can define any restriction for values using functions.
- To define any restrictions for the values of one field, define a function that checks a criteria for the field value and returns Bool, and put its name after a
,
after the field name:
GPA::Float64, "~", GPAcheck
- To define any restrictions for multiple values of a struct, define a function that gets all the variables and checks a criteria and returns Bool, and put its name after a
,
after the struct name:
@aml mutable struct Person "person", check_course
# ...
end
Refer to https://aminya.github.io/AcuteML.jl/dev/valueChecking/ for some of these functions examples.
Optional Fields
- If a field is optional, don't forget to define its type as
UN{}
(Union with Nothing), and set the default value asnothing
.
residence::UN{String}=nothing, "residence-stay" # optional with nothing as default value
funds::UN{String}, "financial-funds" # optional, but you should pass nothing manually in construction
Text Nodes
If the value is going to be in a Text node:
- use
txt"index"
for non-vector field type, whichindex
is an Integer that shows the positon of text node. If you givetxt""
it considers it liketxt"1"
.
textnode_single:String, txt"2"
- use
txt"indices"
for vector field type, whichindices
is an array index that shows the positons of the text nodes. If you givetxt""
it considers it liketxt"[:]"
textnode_vector::Vector{String}, txt"[2:3]"
Note that the vector Text nodes should only be used as the last field of a struct (because possible positons for text node should be known). Alternatively, you can make non-vector separate fields with correct position in the struct definition.
Empty Elements (Self-Closing) Definition
- Use
empty"name"
to define an empty (self-closing) element (e.g.<rest />
)
@aml struct rest empty"~"
end
Example - Simple
using AcuteML
@aml mutable struct body "~"
h1, "~"
p::Vector{String}, "~"
end
@aml mutable struct html doc"html"
body::body, "~"
end
b = body(h1 = "My heading", p = ["Paragraph1", "Paragraph2"])
d = html(body = b)
julia> pprint(d)
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<body>
<h1>My heading</h1>
<p>Paragraph1</p>
<p>Paragraph2</p>
</body>
</html>
Example - Struct Definition
First, we define the structs using @aml
to store the data in:
using AcuteML
# Types definition
# Person Type
@aml mutable struct Person "person", check_course
age::UInt64, "~"
field, "study-field"
GPA::Float64 = 4.5, "~", GPAcheck
courses::Vector{String}, "taken-courses"
professors::UN{DataFrame} = nothing, "table"
id::Int64, att"~"
comment::UN{String} = nothing, txt"end"
end
@aml mutable struct University doc"university"
name, att"university-name"
people::Vector{Person}, "person"
end
# Value Checking Functions
GPAcheck(x) = x <= 4.5 && x >= 0
function check_course(age, field, GPA, courses, professors, id, comment)
if field == "Mechanical Engineering"
relevant = ["Artificial Intelligence", "Robotics", "Machine Design"]
elseif field == "Computer Engineering"
relevant = ["Julia", "Algorithms"]
else
error("study field is not known")
end
return any(in.(courses, Ref(relevant)))
end
Example - Creator
After we defined the structs, we can create instances of them by passing our data to the fields:
P1 = Person(age=24, field="Mechanical Engineering", courses = ["Artificial Intelligence", "Robotics"], id = 1, comment = "He is a genius")
P2 = Person(age=18, field="Computer Engineering", GPA=4, courses=["Julia"], id = 2)
U = University(name="Julia University", people=[P1, P2])
U.people[2].GPA=4.2 # mutability support after Doc creation
# An example that doesn't meet the criteria function for GPA because GPA is more than 4.5
P3 = Person(age=99, field="Macro Wizard", GPA=10, courses=["Julia Magic"], id = 3)
julia>
GPA doesn't meet criteria function
julia> pprint(P1) # or print(P1.aml)
<person id="1">
<age>24</age>
<study-field>Mechanical Engineering</study-field>
<GPA>4.5</GPA>
<taken-courses>Artificial Intelligence</taken-courses>
<taken-courses>Robotics</taken-courses>
He is a genius
</person>
julia> pprint(U) # or print(U.aml)
<?xml version="1.0" encoding="UTF-8"?>
<university university-name="Julia University">
<person id="1">
<age>24</age>
<study-field>Mechanical Engineering</study-field>
<GPA>4.5</GPA>
<taken-courses>Artificial Intelligence</taken-courses>
<taken-courses>Robotics</taken-courses>
He is a genius
</person>
<person id="2">
<age>18</age>
<study-field>Computer Engineering</study-field>
<GPA>4.2</GPA>
<taken-courses>Julia</taken-courses>
</person>
</university>
P3 with Tables.jl type:
Profs1 = DataFrame(course = ["Artificial Intelligence", "Robotics"], professor = ["Prof. A", "Prof. B"] )
P3 = Person(age=24, field="Mechanical Engineering", courses = ["Artificial Intelligence", "Robotics"], professors= Profs1, id = 1)
julia> pprint(P3)
<person id="1">
<age>24</age>
<study-field>Mechanical Engineering</study-field>
<GPA>4.5</GPA>
<taken-courses>Artificial Intelligence</taken-courses>
<taken-courses>Robotics</taken-courses>
<table>
<tr class="header">
<th style="text-align: right; ">course</th>
<th style="text-align: right; ">professor</th>
</tr>
<tr class="subheader headerLastRow">
<th style="text-align: right; ">String</th>
<th style="text-align: right; ">String</th>
</tr>
<tr>
<td style="text-align: right; ">Artificial Intelligence</td>
<td style="text-align: right; ">Prof. A</td>
</tr>
<tr>
<td style="text-align: right; ">Robotics</td>
<td style="text-align: right; ">Prof. B</td>
</tr>
</table>
</person>
Example - Extractor
After we defined the structs, we can automatically extract and store the data in their fields:
using AcuteML
xml = parsexml("""
<?xml version="1.0" encoding="UTF-8"?>
<university university-name="Julia University">
<person id="1">
<age>24</age>
<study-field>Mechanical Engineering</study-field>
<GPA>4.5</GPA>
<taken-courses>Artificial Intelligence</taken-courses>
<taken-courses>Robotics</taken-courses>
He is a genius
</person>
<person id="2">
<age>18</age>
<study-field>Computer Engineering</study-field>
<GPA>4.2</GPA>
<taken-courses>Julia</taken-courses>
</person>
</university>
""")
# extract University
U = University(xml) # StructName(xml) extracts the data and stores them in proper format
# Now you can access all of the data by calling the fieldnames
julia>U.name
"Julia University"
# extract Person
P1 = U.people[1]
julia>P1.age
24
julia>P1.field
Mechanical Engineering
julia>P1.GPA
4.5
julia>P1.courses
["Artificial Intelligence", "Robotics"]
julia>P1.id
1
julia> P1.comment
"He is a genius"
AcuteML.pprint
— Methodpprint(x)
pprint(io, x)
pprint(filename, x)
Pretty prints the xml/html content of a aml type. Also, pretty prints a Node or Document type.
EzXML.parsehtml
— Functionparsehtml(htmlstring)
Parse htmlstring
and create an HTML document.
EzXML.parsexml
— Functionparsexml(xmlstring)
Parse xmlstring
and create an XML document.
EzXML.readhtml
— Functionreadhtml(filename)
Read filename
and create an HTML document.
readhtml(input::IO)
Read input
and create an HTML document.
EzXML.readxml
— Functionreadxml(filename)
Read filename
and create an XML document.
readxml(input::IO)
Read input
and create an XML document.
Templating
AcuteML.newTemplate
— FunctionnewTemplate(name)
Create new destination html file as the template
newTemplate(name, :function)
Prints a function to be used as a template
Examples
# you can create a file and edit the file directly by using
newTemplate("person")
## create person function to store out html template
newTemplate("person", :function)
AcuteML.render2file
— Functionrender2file(destination, overwrite, var...)
render variables passed as an input to the destination file.
You should put var in the destination file/string so var is evaluated there. Pass the variables as keyword arguments with the same name you used in the html string/file. Variables should be string,
If you want to statically overwrite the file pass true
as the 2nd argument to the function. Useful if you don't want a dynamic website.
Examples
# Add the following html code to the generated html file
#=
<person id=$(id)>
<age>$(age)</age>
<study-field>$(field)</study-field>
<GPA>$(GPA)</GPA>
<taken-courses>$(courses[1])</taken-courses>
<taken-courses>$(courses[2])</taken-courses>
</person>
=#
# Specify the template (or its path), and also the variables for rendering
out =render2file("person", false,
id = 1,
age = 24,
field = "Mechanical Engineering",
GPA = 4.5,
courses = ["Artificial Intelligence", "Robotics"])
# you pass `true` as the 2nd argument to owerwrite person.html statically.
Macro Backend
AcuteML.aml_create
— Method@aml creator function
AcuteML.aml_parse
— Method@aml parser function
XML/HTML utilities
AcuteML.createnode
— Functioncreatenode(struct_nodetype)
Function to initialize the aml