Add XML classes

This commit is contained in:
Brandon Robins
2017-10-22 22:47:10 -05:00
parent 50a3472a1f
commit cab55272ca
3 changed files with 180 additions and 0 deletions

View File

@@ -0,0 +1,147 @@
module Calligraphy::XML
class Builder
SUPPORTED_NS_TAGS = %w(
creationdate displayname exclusive getcontentlanguage getcontentlength
getcontenttype getetag getlastmodified href lockdiscovery lockscope
locktype owner write
)
attr_reader :dav_ns, :default_ns, :server_protocol
def initialize(dav_ns: 'D', server_protocol: 'HTTP/1.1')
@dav_ns = dav_ns
@default_ns = { "xmlns:#{@dav_ns}" => 'DAV:' }
@server_protocol = server_protocol
end
def lock_res(activelock_properties)
build :prop do |xml|
xml.lockdiscovery do
activelock_properties.each do |properties|
activelock xml, properties
end
end
end
end
def propfind_res(path, properties)
multistatus do |xml|
href xml, path
propstat xml, properties[:found], :ok
propstat xml, properties[:not_found], :not_found
end
end
def proppatch_res(path, actions)
multistatus do |xml|
href xml, path
propstat xml, actions[:set]
propstat xml, actions[:remove]
end
end
private
def build(tag)
Nokogiri::XML::Builder.new do |xml|
xml[@dav_ns].send(tag, @default_ns) do
yield xml
end
end.to_xml
end
def activelock(xml, property_set)
xml.activelock do
property_set.each do |property|
property_drilldown xml, property
end
end
end
def href(xml, path)
xml.href path
end
def multistatus
build :multistatus do |xml|
xml.response do
yield xml
end
end
end
def prop(xml, property_set)
xml.prop do
property_set.each do |property|
property_drilldown xml, property
end
end
end
def propstat(xml, property_set, status=:ok)
return unless property_set.length > 0
xml.propstat do
prop xml, property_set
status xml, status
end
end
def resourcetype(xml, property)
if property.children.text == 'collection'
xml[@dav_ns].resourcetype do
xml.send 'collection'
end
else
xml[@dav_ns].resourcetype
end
end
def status(xml, status)
xml.status status_message status
end
# NOTE: `xml[@dav_ns].send timeout` results in Timeout being called, so
# we have this timeout method for convenience
def timeout(xml, property)
xml[@dav_ns].timeout do
xml.text property.text
end
end
def property_drilldown(xml, property)
if property.is_a? Array
property.each do |prop|
property_drilldown xml, prop
end
elsif property.children && property.text.nil?
xml.send property.name do
property.children.each do |child|
property_drilldown xml, child
end
end
elsif property.name == 'resourcetype'
resourcetype xml, property
elsif property.name == 'timeout'
timeout xml, property
elsif SUPPORTED_NS_TAGS.include? property.name
xml[@dav_ns].send property.name do
xml.text property.text
end
elsif property.namespace && property.namespace.href
xml.send property.name, xmlns: property.namespace.href do
xml.text property.text
end
else
xml.send property.name, property.text do
xml.parent.namespace = nil
end
end
end
def status_message(status)
status_code = Rack::Utils.status_code status
[@server_protocol, status_code, Rack::Utils::HTTP_STATUS_CODES[status_code]].join ' '
end
end
end

View File

@@ -0,0 +1,10 @@
module Calligraphy::XML
class Namespace
attr_accessor :href, :prefix
def initialize(namespace)
@href = namespace.href if namespace.href
@prefix = namespace.prefix if namespace.prefix
end
end
end

View File

@@ -0,0 +1,23 @@
module Calligraphy::XML
class Node
attr_accessor :children, :name, :namespace, :text
def initialize(node=nil)
unless node.nil?
@name = node.name
@text = node.text unless node.text.empty?
if node.namespace
@namespace = Calligraphy::XML::Namespace.new node.namespace
end
if node.children&.length > 0
@children = []
node.children.each do |child|
@children.push Calligraphy::XML::Node.new child
end
end
end
end
end
end