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