diff --git a/spec/std/xml/xml_spec.cr b/spec/std/xml/xml_spec.cr
index 385f466442ab..2f1131943d00 100644
--- a/spec/std/xml/xml_spec.cr
+++ b/spec/std/xml/xml_spec.cr
@@ -96,6 +96,50 @@ describe XML do
person["id"].should eq("1")
end
+ it "sets node attributes" do
+ doc = XML.parse(<<-XML
+
+
+ John
+
+ XML
+ )
+ person = doc.root.not_nil!
+ person.name.should eq("person")
+ person["id"].should eq "1"
+ person["id"] = "one"
+ person["id"].should eq "one"
+ person["id2"]?.should eq nil
+ person["id2"] = "two"
+ person["id2"].should eq "two"
+ person_s = person.to_s
+ person_s.index("id=\"one\"").should_not eq nil
+ person_s.index("id2=\"two\"").should_not eq nil
+ end
+
+ it "deletes node attributes" do
+ doc = XML.parse(<<-XML
+
+
+ John
+
+ XML
+ )
+ person = doc.root.not_nil!
+ person.name.should eq("person")
+ person["id"].should eq "1"
+ person.delete("id")
+ person["id"]?.should eq nil
+ person["id2"] = "2"
+ deleted_attribute = person.delete("id2")
+ deleted_attribute.should eq "2"
+ deleted_attribute = person.delete("id2")
+ deleted_attribute.should eq nil
+ person_s = person.to_s
+ person_s.index("id=").should eq nil
+ person_s.index("id2=").should eq nil
+ end
+
it "raises exception on empty string" do
expect_raises XML::Error, "Document is empty" do
XML.parse("")
diff --git a/src/xml/attributes.cr b/src/xml/attributes.cr
index a259aa9b2594..52dbd23486e7 100644
--- a/src/xml/attributes.cr
+++ b/src/xml/attributes.cr
@@ -37,6 +37,23 @@ struct XML::Attributes
find { |node| node.name == name }
end
+ def delete(name : String)
+ curr = LibXML.xmlHasProp(@node, name)
+ return nil if curr.null?
+ content = Node.new(curr).content
+ LibXML.xmlRemoveProp(curr)
+ content
+ end
+
+ def []=(name : String, value : String)
+ curr = self[name]?
+ if curr
+ curr.content = value
+ else
+ LibXML.xmlNewProp(@node, name, value)
+ end
+ end
+
def each : Nil
return unless @node.element?
diff --git a/src/xml/libxml2.cr b/src/xml/libxml2.cr
index ec37ea677479..4e64b690c1ae 100644
--- a/src/xml/libxml2.cr
+++ b/src/xml/libxml2.cr
@@ -121,6 +121,10 @@ lib LibXML
fun xmlXPathNodeSetCreate(node : Node*) : NodeSet*
fun xmlXPathNodeSetAddUnique(cur : NodeSet*, val : Node*) : Int
fun xmlNodeGetContent(node : Node*) : UInt8*
+
+ fun xmlNewProp(node : Node*, name : UInt8*, value : UInt8*) : Attr*
+ fun xmlHasProp(node : Node*, name : UInt8*) : Attr*
+ fun xmlRemoveProp(cur : Attr*) : Int
fun xmlNodeSetContent(node : Node*, content : UInt8*)
fun xmlNodeSetName(node : Node*, name : UInt8*)
diff --git a/src/xml/node.cr b/src/xml/node.cr
index ebbd0395f6ff..7de91d233bb8 100644
--- a/src/xml/node.cr
+++ b/src/xml/node.cr
@@ -25,6 +25,18 @@ struct XML::Node
attributes[attribute].content || raise(KeyError.new("Missing attribute: #{attribute}"))
end
+ # sets *attribute* of this node to *value*. Raises `XML::Error` if this node does not support attributes.
+ def []=(name : String, value : String)
+ raise XML::Error.new("Can't set attribute of #{type}", 0) unless element?
+ attributes[name] = value
+ end
+
+ # Deletes attribute given by *name*.
+ # Returns attributes value, or `nil` if attribute not found.
+ def delete(name : String)
+ attributes.delete(name)
+ end
+
# Gets the attribute content for the *attribute* given by name. Returns `nil` if attribute is not found.
def []?(attribute : String) : String?
attributes[attribute]?.try &.content