Skip to content
Browse files

Added attribute declarations

  • Loading branch information...
1 parent 7e7bfda commit ca68f1de4394d97c1b5defc460742453a85c56c1 @oozcitak committed Dec 21, 2013
Showing with 97 additions and 7 deletions.
  1. +65 −0 src/XMLDTDAttList.coffee
  2. +3 −3 src/XMLDTDElement.coffee
  3. +19 −0 src/XMLDocType.coffee
  4. +4 −2 src/XMLStringifier.coffee
  5. +6 −2 test/doctype.coffee
View
65 src/XMLDTDAttList.coffee
@@ -0,0 +1,65 @@
+_ = require 'underscore'
+
+# Represents an attribute list
+module.exports = class XMLDTDAttList
+
+
+ # Initializes a new instance of `XMLDTDAttList`
+ #
+ # `parent` the parent `XMLDocType` element
+ # `elementName` the name of the element containing this attribute
+ # `attributeName` attribute name
+ # `attributeType` type of the attribute (defaults to CDATA)
+ # `defaultValueType` default value type (either #REQUIRED, #IMPLIED, #FIXED or
+ # #DEFAULT) (defaults to #IMPLIED)
+ # `defaultValue` default value of the attribute
+ # (only used for #FIXED or #DEFAULT)
+ constructor: (parent, elementName, attributeName, attributeType, defaultValueType, defaultValue) ->
+ @stringify = parent.stringify
+
+ if not elementName?
+ throw new Error "Missing DTD element name"
+ if not attributeName?
+ throw new Error "Missing DTD attribute name"
+ if not attributeType
+ attributeType = 'CDATA'
+ if not defaultValueType
+ defaultValueType = '#IMPLIED'
+ if defaultValueType.indexOf('#') != 0
+ defaultValueType = '#' + defaultValueType
+ if not defaultValueType.match /^(#REQUIRED|#IMPLIED|#FIXED|#DEFAULT)$/
+ throw new Error "Invalid default value type; expected: #REQUIRED, #IMPLIED, #FIXED or #DEFAULT"
+ if defaultValue and not defaultValueType.match /^(#FIXED|#DEFAULT)$/
+ throw new Error "Default value only applies to #FIXED or #DEFAULT"
+
+ @elementName = @stringify.eleName elementName
+ @attributeName = @stringify.attName attributeName
+ @attributeType = @stringify.dtdAttType attributeType
+ @defaultValue = @stringify.dtdAttDefault defaultValue
+ @defaultValueType = defaultValueType
+
+ # Converts the XML fragment to string
+ #
+ # `options.pretty` pretty prints the result
+ # `options.indent` indentation for pretty print
+ # `options.newline` newline sequence for pretty print
+ toString: (options, level) ->
+ pretty = options?.pretty or false
+ indent = options?.indent or ' '
+ newline = options?.newline or '\n'
+ level or= 0
+
+ space = new Array(level).join(indent)
+
+ r = ''
+
+ r += space if pretty
+
+ r += '<!ATTLIST ' + @elementName + ' ' + @attributeName + ' ' + @attributeType
+ r += ' ' + @defaultValueType if @defaultValueType != '#DEFAULT'
+ r += ' "' + @defaultValue + '"' if @defaultValue
+ r += '>'
+
+ r += newline if pretty
+
+ return r
View
6 src/XMLDTDElement.coffee
@@ -19,7 +19,7 @@ module.exports = class XMLDTDElement
if _.isArray value
value = '(' + value.join(',') + ')'
- @name = @stringify.dtdElementName name
+ @name = @stringify.eleName name
@value = @stringify.dtdElementValue value
@@ -37,10 +37,10 @@ module.exports = class XMLDTDElement
space = new Array(level).join(indent)
r = ''
-
+
r += space if pretty
- r = '<!ELEMENT ' + @name + ' ' + @value + '>'
+ r += '<!ELEMENT ' + @name + ' ' + @value + '>'
r += newline if pretty
View
19 src/XMLDocType.coffee
@@ -36,6 +36,22 @@ module.exports = class XMLDocType
return @
+ # Creates an attribute declaration
+ #
+ # `elementName` the name of the element containing this attribute
+ # `attributeName` attribute name
+ # `attributeType` type of the attribute (defaults to CDATA)
+ # `defaultValueType` default value type (either #REQUIRED, #IMPLIED, #FIXED or
+ # #DEFAULT) (defaults to #IMPLIED)
+ # `defaultValue` default value of the attribute
+ # (only used for #FIXED or #DEFAULT)
+ attList: (elementName, attributeName, attributeType, defaultValueType, defaultValue) ->
+ XMLDTDAttList = require './XMLDTDAttList'
+ child = new XMLDTDAttList @, elementName, attributeName, attributeType, defaultValueType, defaultValue
+ @children.push child
+ return @
+
+
# Gets the root node
root: () ->
@parent.root()
@@ -90,4 +106,7 @@ module.exports = class XMLDocType
# Aliases
ele: (name, value) -> @element name, value
+ att: (elementName, attributeName, attributeType, defaultValueType, defaultValue) ->
+ @attList elementName, attributeName, attributeType, defaultValueType, defaultValue
+ up: () -> @root()
doc: () -> @document()
View
6 src/XMLStringifier.coffee
@@ -58,10 +58,12 @@ module.exports = class XMLStringifier
'' + val or ''
xmlSysID: (val) ->
'' + val or ''
- dtdElementName: (val) ->
- '' + val or ''
dtdElementValue: (val) ->
'' + val or ''
+ dtdAttType: (val) ->
+ '' + val or ''
+ dtdAttDefault: (val) ->
+ if val? then '' + val or '' else val
# strings to match while converting from JS objects
convertAttKey: '@'
View
8 test/doctype.coffee
@@ -65,15 +65,19 @@ vows
topic: () ->
xmlbuilder.create('root')
.dtd({ sysID: 'hello.dtd' })
- .ele('img', 'EMPTY')
- .ele('node')
+ .ele('img', 'EMPTY')
+ .att('img', 'height', 'CDATA', '#REQUIRED')
+ .att('img', 'visible', '(yes|no)', '#DEFAULT', "yes")
+ .ele('node')
.root()
.ele('node').txt('test')
'resulting XML': (topic) ->
xml = '<?xml version="1.0"?>' +
'<!DOCTYPE root SYSTEM "hello.dtd" [' +
'<!ELEMENT img EMPTY>' +
+ '<!ATTLIST img height CDATA #REQUIRED>' +
+ '<!ATTLIST img visible (yes|no) "yes">' +
'<!ELEMENT node (#PCDATA)>' +
']>' +
'<root><node>test</node></root>'

0 comments on commit ca68f1d

Please sign in to comment.
Something went wrong with that request. Please try again.