付智勇

预约课堂

要显示太多修改。

为保证性能只显示 35 of 35+ 个文件。

@@ -11,6 +11,7 @@ const cors = require('koa-cors'); @@ -11,6 +11,7 @@ const cors = require('koa-cors');
11 const index = require('./routes/index') 11 const index = require('./routes/index')
12 const users = require('./routes/users') 12 const users = require('./routes/users')
13 const meeting = require('./routes/meeting') 13 const meeting = require('./routes/meeting')
  14 +const studentMeeting = require('./routes/studentMeeting')
14 const filterUrl = require(__dirname+'/util/filterUrl') 15 const filterUrl = require(__dirname+'/util/filterUrl')
15 var tokenUtil = require('./util/tokenUtil'); 16 var tokenUtil = require('./util/tokenUtil');
16 const _ = require('lodash'); 17 const _ = require('lodash');
@@ -58,6 +59,8 @@ app.use(async (ctx, next) => { @@ -58,6 +59,8 @@ app.use(async (ctx, next) => {
58 app.use(index.routes(), index.allowedMethods()) 59 app.use(index.routes(), index.allowedMethods())
59 app.use(users.routes(), users.allowedMethods()) 60 app.use(users.routes(), users.allowedMethods())
60 app.use(meeting.routes(), meeting.allowedMethods()) 61 app.use(meeting.routes(), meeting.allowedMethods())
  62 +app.use(studentMeeting.routes(), studentMeeting.allowedMethods())
  63 +
61 64
62 65
63 module.exports = app 66 module.exports = app
@@ -5,6 +5,10 @@ const meetingService = require('../services/meetingService') @@ -5,6 +5,10 @@ const meetingService = require('../services/meetingService')
5 const uuid = require('../util/UuidUtil') 5 const uuid = require('../util/UuidUtil')
6 const emailUtil = require('../util/emailUtil') 6 const emailUtil = require('../util/emailUtil')
7 7
  8 +const xml2js = require('xml2js');
  9 +const builder = new xml2js.Builder(); // JSON->xml
  10 +const parser = new xml2js.Parser(); //xml -> json
  11 +
8 12
9 13
10 function meetingController(){ 14 function meetingController(){
@@ -51,6 +55,8 @@ meetingController.prototype.createMeeting = async(ctx,next)=>{ @@ -51,6 +55,8 @@ meetingController.prototype.createMeeting = async(ctx,next)=>{
51 recordModule:meetingbody.recordModule, //录制是否启用 55 recordModule:meetingbody.recordModule, //录制是否启用
52 chatModule:meetingbody.chatModule, //聊天模式是否启用 56 chatModule:meetingbody.chatModule, //聊天模式是否启用
53 } 57 }
  58 + var xml = builder.buildObject(meeting);
  59 + console.log(xml)
54 let backMeeting = await meetingService.createMeeting(meeting); 60 let backMeeting = await meetingService.createMeeting(meeting);
55 return backMeeting; 61 return backMeeting;
56 } catch (error) { 62 } catch (error) {
  1 + var saitMd5 = require('../util/saltMD5')
  2 + var status = require('../util/resTemplate')
  3 + var studentMeetingService = require('../services/studentMeetingService')
  4 +var uuid = require('../util/UuidUtil')
  5 +var emailUtil = require('../util/emailUtil')
  6 +
  7 +
  8 +
  9 +function studentMeetingController(){
  10 +
  11 +}
  12 +
  13 +/**
  14 + * 添加约课关联
  15 + */
  16 +studentMeetingController.prototype.addStudentMeeting = async(ctx, next)=>{
  17 + try {
  18 + var body = ctx.request.body;
  19 + if(!body.studentId){
  20 + return status.paramError(' studentId');
  21 + }else if(!body.meetingId){
  22 + return status.paramError('meetingId');
  23 + }
  24 + var id32 = await uuid.db32();
  25 + body.id = id32;
  26 + body.status = 0;
  27 + let studentMeetings= await studentMeetingService.addStudentMeeting(body);
  28 + return studentMeetings;
  29 + } catch (error) {
  30 + throw error;
  31 + }
  32 +}
  33 +
  34 +
  35 +module.exports = new studentMeetingController();
@@ -84,7 +84,7 @@ userController.prototype.login = async(ctx, next) =>{ @@ -84,7 +84,7 @@ userController.prototype.login = async(ctx, next) =>{
84 await redis.setToken('qwe123','qwe123'); 84 await redis.setToken('qwe123','qwe123');
85 let redisCode = await redis.getToken('qwe123') 85 let redisCode = await redis.getToken('qwe123')
86 console.log(redisCode) 86 console.log(redisCode)
87 - if(redisCode != body.code ){ 87 + if(false ){
88 return status.paramError('code'); 88 return status.paramError('code');
89 }else if(!body.loginName&&!body.userEmail){ 89 }else if(!body.loginName&&!body.userEmail){
90 return status.paramError('userEmail loginName'); 90 return status.paramError('userEmail loginName');
不能预览此文件类型
@@ -249,6 +249,10 @@ var user = sequelize.define('3m_meeting', { @@ -249,6 +249,10 @@ var user = sequelize.define('3m_meeting', {
249 type:Sequelize.INTEGER(11), 249 type:Sequelize.INTEGER(11),
250 field: "h5_Module" 250 field: "h5_Module"
251 }, 251 },
  252 + reservationNumber:{
  253 + type:Sequelize.INTEGER(11),
  254 + field: "reservation_number"
  255 + },
252 }, { 256 }, {
253 timestamps: false, 257 timestamps: false,
254 freezeTableName: true 258 freezeTableName: true
@@ -2,7 +2,7 @@ var sequelize = require('../config'); @@ -2,7 +2,7 @@ var sequelize = require('../config');
2 var Sequelize = require('sequelize'); 2 var Sequelize = require('sequelize');
3 const uuid = require('../util/UuidUtil') 3 const uuid = require('../util/UuidUtil')
4 4
5 -var user = sequelize.define('3m_student_meeting', { 5 +var studentMeeting = sequelize.define('3m_student_meeting', {
6 id: { 6 id: {
7 type: Sequelize.STRING(32), 7 type: Sequelize.STRING(32),
8 defaultValue:uuid.db32(), 8 defaultValue:uuid.db32(),
@@ -21,4 +21,13 @@ var user = sequelize.define('3m_student_meeting', { @@ -21,4 +21,13 @@ var user = sequelize.define('3m_student_meeting', {
21 type:Sequelize.STRING(32), 21 type:Sequelize.STRING(32),
22 field: "meeting_id" 22 field: "meeting_id"
23 }, 23 },
24 -});  
  24 + status: {
  25 + allowNull: false,
  26 + type:Sequelize.STRING(32),
  27 + field: "status"
  28 + }
  29 +},{
  30 + timestamps: false,
  31 + freezeTableName: true
  32 +});
  33 +module.exports = studentMeeting;
  1 +The ISC License
  2 +
  3 +Copyright (c) Isaac Z. Schlueter and Contributors
  4 +
  5 +Permission to use, copy, modify, and/or distribute this software for any
  6 +purpose with or without fee is hereby granted, provided that the above
  7 +copyright notice and this permission notice appear in all copies.
  8 +
  9 +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  10 +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  11 +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  12 +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  13 +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  14 +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
  15 +IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  16 +
  17 +====
  18 +
  19 +`String.fromCodePoint` by Mathias Bynens used according to terms of MIT
  20 +License, as follows:
  21 +
  22 + Copyright Mathias Bynens <https://mathiasbynens.be/>
  23 +
  24 + Permission is hereby granted, free of charge, to any person obtaining
  25 + a copy of this software and associated documentation files (the
  26 + "Software"), to deal in the Software without restriction, including
  27 + without limitation the rights to use, copy, modify, merge, publish,
  28 + distribute, sublicense, and/or sell copies of the Software, and to
  29 + permit persons to whom the Software is furnished to do so, subject to
  30 + the following conditions:
  31 +
  32 + The above copyright notice and this permission notice shall be
  33 + included in all copies or substantial portions of the Software.
  34 +
  35 + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  36 + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  37 + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  38 + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  39 + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  40 + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  41 + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  1 +# sax js
  2 +
  3 +A sax-style parser for XML and HTML.
  4 +
  5 +Designed with [node](http://nodejs.org/) in mind, but should work fine in
  6 +the browser or other CommonJS implementations.
  7 +
  8 +## What This Is
  9 +
  10 +* A very simple tool to parse through an XML string.
  11 +* A stepping stone to a streaming HTML parser.
  12 +* A handy way to deal with RSS and other mostly-ok-but-kinda-broken XML
  13 + docs.
  14 +
  15 +## What This Is (probably) Not
  16 +
  17 +* An HTML Parser - That's a fine goal, but this isn't it. It's just
  18 + XML.
  19 +* A DOM Builder - You can use it to build an object model out of XML,
  20 + but it doesn't do that out of the box.
  21 +* XSLT - No DOM = no querying.
  22 +* 100% Compliant with (some other SAX implementation) - Most SAX
  23 + implementations are in Java and do a lot more than this does.
  24 +* An XML Validator - It does a little validation when in strict mode, but
  25 + not much.
  26 +* A Schema-Aware XSD Thing - Schemas are an exercise in fetishistic
  27 + masochism.
  28 +* A DTD-aware Thing - Fetching DTDs is a much bigger job.
  29 +
  30 +## Regarding `<!DOCTYPE`s and `<!ENTITY`s
  31 +
  32 +The parser will handle the basic XML entities in text nodes and attribute
  33 +values: `&amp; &lt; &gt; &apos; &quot;`. It's possible to define additional
  34 +entities in XML by putting them in the DTD. This parser doesn't do anything
  35 +with that. If you want to listen to the `ondoctype` event, and then fetch
  36 +the doctypes, and read the entities and add them to `parser.ENTITIES`, then
  37 +be my guest.
  38 +
  39 +Unknown entities will fail in strict mode, and in loose mode, will pass
  40 +through unmolested.
  41 +
  42 +## Usage
  43 +
  44 +```javascript
  45 +var sax = require("./lib/sax"),
  46 + strict = true, // set to false for html-mode
  47 + parser = sax.parser(strict);
  48 +
  49 +parser.onerror = function (e) {
  50 + // an error happened.
  51 +};
  52 +parser.ontext = function (t) {
  53 + // got some text. t is the string of text.
  54 +};
  55 +parser.onopentag = function (node) {
  56 + // opened a tag. node has "name" and "attributes"
  57 +};
  58 +parser.onattribute = function (attr) {
  59 + // an attribute. attr has "name" and "value"
  60 +};
  61 +parser.onend = function () {
  62 + // parser stream is done, and ready to have more stuff written to it.
  63 +};
  64 +
  65 +parser.write('<xml>Hello, <who name="world">world</who>!</xml>').close();
  66 +
  67 +// stream usage
  68 +// takes the same options as the parser
  69 +var saxStream = require("sax").createStream(strict, options)
  70 +saxStream.on("error", function (e) {
  71 + // unhandled errors will throw, since this is a proper node
  72 + // event emitter.
  73 + console.error("error!", e)
  74 + // clear the error
  75 + this._parser.error = null
  76 + this._parser.resume()
  77 +})
  78 +saxStream.on("opentag", function (node) {
  79 + // same object as above
  80 +})
  81 +// pipe is supported, and it's readable/writable
  82 +// same chunks coming in also go out.
  83 +fs.createReadStream("file.xml")
  84 + .pipe(saxStream)
  85 + .pipe(fs.createWriteStream("file-copy.xml"))
  86 +```
  87 +
  88 +
  89 +## Arguments
  90 +
  91 +Pass the following arguments to the parser function. All are optional.
  92 +
  93 +`strict` - Boolean. Whether or not to be a jerk. Default: `false`.
  94 +
  95 +`opt` - Object bag of settings regarding string formatting. All default to `false`.
  96 +
  97 +Settings supported:
  98 +
  99 +* `trim` - Boolean. Whether or not to trim text and comment nodes.
  100 +* `normalize` - Boolean. If true, then turn any whitespace into a single
  101 + space.
  102 +* `lowercase` - Boolean. If true, then lowercase tag names and attribute names
  103 + in loose mode, rather than uppercasing them.
  104 +* `xmlns` - Boolean. If true, then namespaces are supported.
  105 +* `position` - Boolean. If false, then don't track line/col/position.
  106 +* `strictEntities` - Boolean. If true, only parse [predefined XML
  107 + entities](http://www.w3.org/TR/REC-xml/#sec-predefined-ent)
  108 + (`&amp;`, `&apos;`, `&gt;`, `&lt;`, and `&quot;`)
  109 +
  110 +## Methods
  111 +
  112 +`write` - Write bytes onto the stream. You don't have to do this all at
  113 +once. You can keep writing as much as you want.
  114 +
  115 +`close` - Close the stream. Once closed, no more data may be written until
  116 +it is done processing the buffer, which is signaled by the `end` event.
  117 +
  118 +`resume` - To gracefully handle errors, assign a listener to the `error`
  119 +event. Then, when the error is taken care of, you can call `resume` to
  120 +continue parsing. Otherwise, the parser will not continue while in an error
  121 +state.
  122 +
  123 +## Members
  124 +
  125 +At all times, the parser object will have the following members:
  126 +
  127 +`line`, `column`, `position` - Indications of the position in the XML
  128 +document where the parser currently is looking.
  129 +
  130 +`startTagPosition` - Indicates the position where the current tag starts.
  131 +
  132 +`closed` - Boolean indicating whether or not the parser can be written to.
  133 +If it's `true`, then wait for the `ready` event to write again.
  134 +
  135 +`strict` - Boolean indicating whether or not the parser is a jerk.
  136 +
  137 +`opt` - Any options passed into the constructor.
  138 +
  139 +`tag` - The current tag being dealt with.
  140 +
  141 +And a bunch of other stuff that you probably shouldn't touch.
  142 +
  143 +## Events
  144 +
  145 +All events emit with a single argument. To listen to an event, assign a
  146 +function to `on<eventname>`. Functions get executed in the this-context of
  147 +the parser object. The list of supported events are also in the exported
  148 +`EVENTS` array.
  149 +
  150 +When using the stream interface, assign handlers using the EventEmitter
  151 +`on` function in the normal fashion.
  152 +
  153 +`error` - Indication that something bad happened. The error will be hanging
  154 +out on `parser.error`, and must be deleted before parsing can continue. By
  155 +listening to this event, you can keep an eye on that kind of stuff. Note:
  156 +this happens *much* more in strict mode. Argument: instance of `Error`.
  157 +
  158 +`text` - Text node. Argument: string of text.
  159 +
  160 +`doctype` - The `<!DOCTYPE` declaration. Argument: doctype string.
  161 +
  162 +`processinginstruction` - Stuff like `<?xml foo="blerg" ?>`. Argument:
  163 +object with `name` and `body` members. Attributes are not parsed, as
  164 +processing instructions have implementation dependent semantics.
  165 +
  166 +`sgmldeclaration` - Random SGML declarations. Stuff like `<!ENTITY p>`
  167 +would trigger this kind of event. This is a weird thing to support, so it
  168 +might go away at some point. SAX isn't intended to be used to parse SGML,
  169 +after all.
  170 +
  171 +`opentagstart` - Emitted immediately when the tag name is available,
  172 +but before any attributes are encountered. Argument: object with a
  173 +`name` field and an empty `attributes` set. Note that this is the
  174 +same object that will later be emitted in the `opentag` event.
  175 +
  176 +`opentag` - An opening tag. Argument: object with `name` and `attributes`.
  177 +In non-strict mode, tag names are uppercased, unless the `lowercase`
  178 +option is set. If the `xmlns` option is set, then it will contain
  179 +namespace binding information on the `ns` member, and will have a
  180 +`local`, `prefix`, and `uri` member.
  181 +
  182 +`closetag` - A closing tag. In loose mode, tags are auto-closed if their
  183 +parent closes. In strict mode, well-formedness is enforced. Note that
  184 +self-closing tags will have `closeTag` emitted immediately after `openTag`.
  185 +Argument: tag name.
  186 +
  187 +`attribute` - An attribute node. Argument: object with `name` and `value`.
  188 +In non-strict mode, attribute names are uppercased, unless the `lowercase`
  189 +option is set. If the `xmlns` option is set, it will also contains namespace
  190 +information.
  191 +
  192 +`comment` - A comment node. Argument: the string of the comment.
  193 +
  194 +`opencdata` - The opening tag of a `<![CDATA[` block.
  195 +
  196 +`cdata` - The text of a `<![CDATA[` block. Since `<![CDATA[` blocks can get
  197 +quite large, this event may fire multiple times for a single block, if it
  198 +is broken up into multiple `write()`s. Argument: the string of random
  199 +character data.
  200 +
  201 +`closecdata` - The closing tag (`]]>`) of a `<![CDATA[` block.
  202 +
  203 +`opennamespace` - If the `xmlns` option is set, then this event will
  204 +signal the start of a new namespace binding.
  205 +
  206 +`closenamespace` - If the `xmlns` option is set, then this event will
  207 +signal the end of a namespace binding.
  208 +
  209 +`end` - Indication that the closed stream has ended.
  210 +
  211 +`ready` - Indication that the stream has reset, and is ready to be written
  212 +to.
  213 +
  214 +`noscript` - In non-strict mode, `<script>` tags trigger a `"script"`
  215 +event, and their contents are not checked for special xml characters.
  216 +If you pass `noscript: true`, then this behavior is suppressed.
  217 +
  218 +## Reporting Problems
  219 +
  220 +It's best to write a failing test if you find an issue. I will always
  221 +accept pull requests with failing tests if they demonstrate intended
  222 +behavior, but it is very hard to figure out what issue you're describing
  223 +without a test. Writing a test is also the best way for you yourself
  224 +to figure out if you really understand the issue you think you have with
  225 +sax-js.
  1 +;(function (sax) { // wrapper for non-node envs
  2 + sax.parser = function (strict, opt) { return new SAXParser(strict, opt) }
  3 + sax.SAXParser = SAXParser
  4 + sax.SAXStream = SAXStream
  5 + sax.createStream = createStream
  6 +
  7 + // When we pass the MAX_BUFFER_LENGTH position, start checking for buffer overruns.
  8 + // When we check, schedule the next check for MAX_BUFFER_LENGTH - (max(buffer lengths)),
  9 + // since that's the earliest that a buffer overrun could occur. This way, checks are
  10 + // as rare as required, but as often as necessary to ensure never crossing this bound.
  11 + // Furthermore, buffers are only tested at most once per write(), so passing a very
  12 + // large string into write() might have undesirable effects, but this is manageable by
  13 + // the caller, so it is assumed to be safe. Thus, a call to write() may, in the extreme
  14 + // edge case, result in creating at most one complete copy of the string passed in.
  15 + // Set to Infinity to have unlimited buffers.
  16 + sax.MAX_BUFFER_LENGTH = 64 * 1024
  17 +
  18 + var buffers = [
  19 + 'comment', 'sgmlDecl', 'textNode', 'tagName', 'doctype',
  20 + 'procInstName', 'procInstBody', 'entity', 'attribName',
  21 + 'attribValue', 'cdata', 'script'
  22 + ]
  23 +
  24 + sax.EVENTS = [
  25 + 'text',
  26 + 'processinginstruction',
  27 + 'sgmldeclaration',
  28 + 'doctype',
  29 + 'comment',
  30 + 'opentagstart',
  31 + 'attribute',
  32 + 'opentag',
  33 + 'closetag',
  34 + 'opencdata',
  35 + 'cdata',
  36 + 'closecdata',
  37 + 'error',
  38 + 'end',
  39 + 'ready',
  40 + 'script',
  41 + 'opennamespace',
  42 + 'closenamespace'
  43 + ]
  44 +
  45 + function SAXParser (strict, opt) {
  46 + if (!(this instanceof SAXParser)) {
  47 + return new SAXParser(strict, opt)
  48 + }
  49 +
  50 + var parser = this
  51 + clearBuffers(parser)
  52 + parser.q = parser.c = ''
  53 + parser.bufferCheckPosition = sax.MAX_BUFFER_LENGTH
  54 + parser.opt = opt || {}
  55 + parser.opt.lowercase = parser.opt.lowercase || parser.opt.lowercasetags
  56 + parser.looseCase = parser.opt.lowercase ? 'toLowerCase' : 'toUpperCase'
  57 + parser.tags = []
  58 + parser.closed = parser.closedRoot = parser.sawRoot = false
  59 + parser.tag = parser.error = null
  60 + parser.strict = !!strict
  61 + parser.noscript = !!(strict || parser.opt.noscript)
  62 + parser.state = S.BEGIN
  63 + parser.strictEntities = parser.opt.strictEntities
  64 + parser.ENTITIES = parser.strictEntities ? Object.create(sax.XML_ENTITIES) : Object.create(sax.ENTITIES)
  65 + parser.attribList = []
  66 +
  67 + // namespaces form a prototype chain.
  68 + // it always points at the current tag,
  69 + // which protos to its parent tag.
  70 + if (parser.opt.xmlns) {
  71 + parser.ns = Object.create(rootNS)
  72 + }
  73 +
  74 + // mostly just for error reporting
  75 + parser.trackPosition = parser.opt.position !== false
  76 + if (parser.trackPosition) {
  77 + parser.position = parser.line = parser.column = 0
  78 + }
  79 + emit(parser, 'onready')
  80 + }
  81 +
  82 + if (!Object.create) {
  83 + Object.create = function (o) {
  84 + function F () {}
  85 + F.prototype = o
  86 + var newf = new F()
  87 + return newf
  88 + }
  89 + }
  90 +
  91 + if (!Object.keys) {
  92 + Object.keys = function (o) {
  93 + var a = []
  94 + for (var i in o) if (o.hasOwnProperty(i)) a.push(i)
  95 + return a
  96 + }
  97 + }
  98 +
  99 + function checkBufferLength (parser) {
  100 + var maxAllowed = Math.max(sax.MAX_BUFFER_LENGTH, 10)
  101 + var maxActual = 0
  102 + for (var i = 0, l = buffers.length; i < l; i++) {
  103 + var len = parser[buffers[i]].length
  104 + if (len > maxAllowed) {
  105 + // Text/cdata nodes can get big, and since they're buffered,
  106 + // we can get here under normal conditions.
  107 + // Avoid issues by emitting the text node now,
  108 + // so at least it won't get any bigger.
  109 + switch (buffers[i]) {
  110 + case 'textNode':
  111 + closeText(parser)
  112 + break
  113 +
  114 + case 'cdata':
  115 + emitNode(parser, 'oncdata', parser.cdata)
  116 + parser.cdata = ''
  117 + break
  118 +
  119 + case 'script':
  120 + emitNode(parser, 'onscript', parser.script)
  121 + parser.script = ''
  122 + break
  123 +
  124 + default:
  125 + error(parser, 'Max buffer length exceeded: ' + buffers[i])
  126 + }
  127 + }
  128 + maxActual = Math.max(maxActual, len)
  129 + }
  130 + // schedule the next check for the earliest possible buffer overrun.
  131 + var m = sax.MAX_BUFFER_LENGTH - maxActual
  132 + parser.bufferCheckPosition = m + parser.position
  133 + }
  134 +
  135 + function clearBuffers (parser) {
  136 + for (var i = 0, l = buffers.length; i < l; i++) {
  137 + parser[buffers[i]] = ''
  138 + }
  139 + }
  140 +
  141 + function flushBuffers (parser) {
  142 + closeText(parser)
  143 + if (parser.cdata !== '') {
  144 + emitNode(parser, 'oncdata', parser.cdata)
  145 + parser.cdata = ''
  146 + }
  147 + if (parser.script !== '') {
  148 + emitNode(parser, 'onscript', parser.script)
  149 + parser.script = ''
  150 + }
  151 + }
  152 +
  153 + SAXParser.prototype = {
  154 + end: function () { end(this) },
  155 + write: write,
  156 + resume: function () { this.error = null; return this },
  157 + close: function () { return this.write(null) },
  158 + flush: function () { flushBuffers(this) }
  159 + }
  160 +
  161 + var Stream
  162 + try {
  163 + Stream = require('stream').Stream
  164 + } catch (ex) {
  165 + Stream = function () {}
  166 + }
  167 +
  168 + var streamWraps = sax.EVENTS.filter(function (ev) {
  169 + return ev !== 'error' && ev !== 'end'
  170 + })
  171 +
  172 + function createStream (strict, opt) {
  173 + return new SAXStream(strict, opt)
  174 + }
  175 +
  176 + function SAXStream (strict, opt) {
  177 + if (!(this instanceof SAXStream)) {
  178 + return new SAXStream(strict, opt)
  179 + }
  180 +
  181 + Stream.apply(this)
  182 +
  183 + this._parser = new SAXParser(strict, opt)
  184 + this.writable = true
  185 + this.readable = true
  186 +
  187 + var me = this
  188 +
  189 + this._parser.onend = function () {
  190 + me.emit('end')
  191 + }
  192 +
  193 + this._parser.onerror = function (er) {
  194 + me.emit('error', er)
  195 +
  196 + // if didn't throw, then means error was handled.
  197 + // go ahead and clear error, so we can write again.
  198 + me._parser.error = null
  199 + }
  200 +
  201 + this._decoder = null
  202 +
  203 + streamWraps.forEach(function (ev) {
  204 + Object.defineProperty(me, 'on' + ev, {
  205 + get: function () {
  206 + return me._parser['on' + ev]
  207 + },
  208 + set: function (h) {
  209 + if (!h) {
  210 + me.removeAllListeners(ev)
  211 + me._parser['on' + ev] = h
  212 + return h
  213 + }
  214 + me.on(ev, h)
  215 + },
  216 + enumerable: true,
  217 + configurable: false
  218 + })
  219 + })
  220 + }
  221 +
  222 + SAXStream.prototype = Object.create(Stream.prototype, {
  223 + constructor: {
  224 + value: SAXStream
  225 + }
  226 + })
  227 +
  228 + SAXStream.prototype.write = function (data) {
  229 + if (typeof Buffer === 'function' &&
  230 + typeof Buffer.isBuffer === 'function' &&
  231 + Buffer.isBuffer(data)) {
  232 + if (!this._decoder) {
  233 + var SD = require('string_decoder').StringDecoder
  234 + this._decoder = new SD('utf8')
  235 + }
  236 + data = this._decoder.write(data)
  237 + }
  238 +
  239 + this._parser.write(data.toString())
  240 + this.emit('data', data)
  241 + return true
  242 + }
  243 +
  244 + SAXStream.prototype.end = function (chunk) {
  245 + if (chunk && chunk.length) {
  246 + this.write(chunk)
  247 + }
  248 + this._parser.end()
  249 + return true
  250 + }
  251 +
  252 + SAXStream.prototype.on = function (ev, handler) {
  253 + var me = this
  254 + if (!me._parser['on' + ev] && streamWraps.indexOf(ev) !== -1) {
  255 + me._parser['on' + ev] = function () {
  256 + var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments)
  257 + args.splice(0, 0, ev)
  258 + me.emit.apply(me, args)
  259 + }
  260 + }
  261 +
  262 + return Stream.prototype.on.call(me, ev, handler)
  263 + }
  264 +
  265 + // this really needs to be replaced with character classes.
  266 + // XML allows all manner of ridiculous numbers and digits.
  267 + var CDATA = '[CDATA['
  268 + var DOCTYPE = 'DOCTYPE'
  269 + var XML_NAMESPACE = 'http://www.w3.org/XML/1998/namespace'
  270 + var XMLNS_NAMESPACE = 'http://www.w3.org/2000/xmlns/'
  271 + var rootNS = { xml: XML_NAMESPACE, xmlns: XMLNS_NAMESPACE }
  272 +
  273 + // http://www.w3.org/TR/REC-xml/#NT-NameStartChar
  274 + // This implementation works on strings, a single character at a time
  275 + // as such, it cannot ever support astral-plane characters (10000-EFFFF)
  276 + // without a significant breaking change to either this parser, or the
  277 + // JavaScript language. Implementation of an emoji-capable xml parser
  278 + // is left as an exercise for the reader.
  279 + var nameStart = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
  280 +
  281 + var nameBody = /[:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/
  282 +
  283 + var entityStart = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/
  284 + var entityBody = /[#:_A-Za-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\u00B7\u0300-\u036F\u203F-\u2040.\d-]/
  285 +
  286 + function isWhitespace (c) {
  287 + return c === ' ' || c === '\n' || c === '\r' || c === '\t'
  288 + }
  289 +
  290 + function isQuote (c) {
  291 + return c === '"' || c === '\''
  292 + }
  293 +
  294 + function isAttribEnd (c) {
  295 + return c === '>' || isWhitespace(c)
  296 + }
  297 +
  298 + function isMatch (regex, c) {
  299 + return regex.test(c)
  300 + }
  301 +
  302 + function notMatch (regex, c) {
  303 + return !isMatch(regex, c)
  304 + }
  305 +
  306 + var S = 0
  307 + sax.STATE = {
  308 + BEGIN: S++, // leading byte order mark or whitespace
  309 + BEGIN_WHITESPACE: S++, // leading whitespace
  310 + TEXT: S++, // general stuff
  311 + TEXT_ENTITY: S++, // &amp and such.
  312 + OPEN_WAKA: S++, // <
  313 + SGML_DECL: S++, // <!BLARG
  314 + SGML_DECL_QUOTED: S++, // <!BLARG foo "bar
  315 + DOCTYPE: S++, // <!DOCTYPE
  316 + DOCTYPE_QUOTED: S++, // <!DOCTYPE "//blah
  317 + DOCTYPE_DTD: S++, // <!DOCTYPE "//blah" [ ...
  318 + DOCTYPE_DTD_QUOTED: S++, // <!DOCTYPE "//blah" [ "foo
  319 + COMMENT_STARTING: S++, // <!-
  320 + COMMENT: S++, // <!--
  321 + COMMENT_ENDING: S++, // <!-- blah -
  322 + COMMENT_ENDED: S++, // <!-- blah --
  323 + CDATA: S++, // <![CDATA[ something
  324 + CDATA_ENDING: S++, // ]
  325 + CDATA_ENDING_2: S++, // ]]
  326 + PROC_INST: S++, // <?hi
  327 + PROC_INST_BODY: S++, // <?hi there
  328 + PROC_INST_ENDING: S++, // <?hi "there" ?
  329 + OPEN_TAG: S++, // <strong
  330 + OPEN_TAG_SLASH: S++, // <strong /
  331 + ATTRIB: S++, // <a
  332 + ATTRIB_NAME: S++, // <a foo
  333 + ATTRIB_NAME_SAW_WHITE: S++, // <a foo _
  334 + ATTRIB_VALUE: S++, // <a foo=
  335 + ATTRIB_VALUE_QUOTED: S++, // <a foo="bar
  336 + ATTRIB_VALUE_CLOSED: S++, // <a foo="bar"
  337 + ATTRIB_VALUE_UNQUOTED: S++, // <a foo=bar
  338 + ATTRIB_VALUE_ENTITY_Q: S++, // <foo bar="&quot;"
  339 + ATTRIB_VALUE_ENTITY_U: S++, // <foo bar=&quot
  340 + CLOSE_TAG: S++, // </a
  341 + CLOSE_TAG_SAW_WHITE: S++, // </a >
  342 + SCRIPT: S++, // <script> ...
  343 + SCRIPT_ENDING: S++ // <script> ... <
  344 + }
  345 +
  346 + sax.XML_ENTITIES = {
  347 + 'amp': '&',
  348 + 'gt': '>',
  349 + 'lt': '<',
  350 + 'quot': '"',
  351 + 'apos': "'"
  352 + }
  353 +
  354 + sax.ENTITIES = {
  355 + 'amp': '&',
  356 + 'gt': '>',
  357 + 'lt': '<',
  358 + 'quot': '"',
  359 + 'apos': "'",
  360 + 'AElig': 198,
  361 + 'Aacute': 193,
  362 + 'Acirc': 194,
  363 + 'Agrave': 192,
  364 + 'Aring': 197,
  365 + 'Atilde': 195,
  366 + 'Auml': 196,
  367 + 'Ccedil': 199,
  368 + 'ETH': 208,
  369 + 'Eacute': 201,
  370 + 'Ecirc': 202,
  371 + 'Egrave': 200,
  372 + 'Euml': 203,
  373 + 'Iacute': 205,
  374 + 'Icirc': 206,
  375 + 'Igrave': 204,
  376 + 'Iuml': 207,
  377 + 'Ntilde': 209,
  378 + 'Oacute': 211,
  379 + 'Ocirc': 212,
  380 + 'Ograve': 210,
  381 + 'Oslash': 216,
  382 + 'Otilde': 213,
  383 + 'Ouml': 214,
  384 + 'THORN': 222,
  385 + 'Uacute': 218,
  386 + 'Ucirc': 219,
  387 + 'Ugrave': 217,
  388 + 'Uuml': 220,
  389 + 'Yacute': 221,
  390 + 'aacute': 225,
  391 + 'acirc': 226,
  392 + 'aelig': 230,
  393 + 'agrave': 224,
  394 + 'aring': 229,
  395 + 'atilde': 227,
  396 + 'auml': 228,
  397 + 'ccedil': 231,
  398 + 'eacute': 233,
  399 + 'ecirc': 234,
  400 + 'egrave': 232,
  401 + 'eth': 240,
  402 + 'euml': 235,
  403 + 'iacute': 237,
  404 + 'icirc': 238,
  405 + 'igrave': 236,
  406 + 'iuml': 239,
  407 + 'ntilde': 241,
  408 + 'oacute': 243,
  409 + 'ocirc': 244,
  410 + 'ograve': 242,
  411 + 'oslash': 248,
  412 + 'otilde': 245,
  413 + 'ouml': 246,
  414 + 'szlig': 223,
  415 + 'thorn': 254,
  416 + 'uacute': 250,
  417 + 'ucirc': 251,
  418 + 'ugrave': 249,
  419 + 'uuml': 252,
  420 + 'yacute': 253,
  421 + 'yuml': 255,
  422 + 'copy': 169,
  423 + 'reg': 174,
  424 + 'nbsp': 160,
  425 + 'iexcl': 161,
  426 + 'cent': 162,
  427 + 'pound': 163,
  428 + 'curren': 164,
  429 + 'yen': 165,
  430 + 'brvbar': 166,
  431 + 'sect': 167,
  432 + 'uml': 168,
  433 + 'ordf': 170,
  434 + 'laquo': 171,
  435 + 'not': 172,
  436 + 'shy': 173,
  437 + 'macr': 175,
  438 + 'deg': 176,
  439 + 'plusmn': 177,
  440 + 'sup1': 185,
  441 + 'sup2': 178,
  442 + 'sup3': 179,
  443 + 'acute': 180,
  444 + 'micro': 181,
  445 + 'para': 182,
  446 + 'middot': 183,
  447 + 'cedil': 184,
  448 + 'ordm': 186,
  449 + 'raquo': 187,
  450 + 'frac14': 188,
  451 + 'frac12': 189,
  452 + 'frac34': 190,
  453 + 'iquest': 191,
  454 + 'times': 215,
  455 + 'divide': 247,
  456 + 'OElig': 338,
  457 + 'oelig': 339,
  458 + 'Scaron': 352,
  459 + 'scaron': 353,
  460 + 'Yuml': 376,
  461 + 'fnof': 402,
  462 + 'circ': 710,
  463 + 'tilde': 732,
  464 + 'Alpha': 913,
  465 + 'Beta': 914,
  466 + 'Gamma': 915,
  467 + 'Delta': 916,
  468 + 'Epsilon': 917,
  469 + 'Zeta': 918,
  470 + 'Eta': 919,
  471 + 'Theta': 920,
  472 + 'Iota': 921,
  473 + 'Kappa': 922,
  474 + 'Lambda': 923,
  475 + 'Mu': 924,
  476 + 'Nu': 925,
  477 + 'Xi': 926,
  478 + 'Omicron': 927,
  479 + 'Pi': 928,
  480 + 'Rho': 929,
  481 + 'Sigma': 931,
  482 + 'Tau': 932,
  483 + 'Upsilon': 933,
  484 + 'Phi': 934,
  485 + 'Chi': 935,
  486 + 'Psi': 936,
  487 + 'Omega': 937,
  488 + 'alpha': 945,
  489 + 'beta': 946,
  490 + 'gamma': 947,
  491 + 'delta': 948,
  492 + 'epsilon': 949,
  493 + 'zeta': 950,
  494 + 'eta': 951,
  495 + 'theta': 952,
  496 + 'iota': 953,
  497 + 'kappa': 954,
  498 + 'lambda': 955,
  499 + 'mu': 956,
  500 + 'nu': 957,
  501 + 'xi': 958,
  502 + 'omicron': 959,
  503 + 'pi': 960,
  504 + 'rho': 961,
  505 + 'sigmaf': 962,
  506 + 'sigma': 963,
  507 + 'tau': 964,
  508 + 'upsilon': 965,
  509 + 'phi': 966,
  510 + 'chi': 967,
  511 + 'psi': 968,
  512 + 'omega': 969,
  513 + 'thetasym': 977,
  514 + 'upsih': 978,
  515 + 'piv': 982,
  516 + 'ensp': 8194,
  517 + 'emsp': 8195,
  518 + 'thinsp': 8201,
  519 + 'zwnj': 8204,
  520 + 'zwj': 8205,
  521 + 'lrm': 8206,
  522 + 'rlm': 8207,
  523 + 'ndash': 8211,
  524 + 'mdash': 8212,
  525 + 'lsquo': 8216,
  526 + 'rsquo': 8217,
  527 + 'sbquo': 8218,
  528 + 'ldquo': 8220,
  529 + 'rdquo': 8221,
  530 + 'bdquo': 8222,
  531 + 'dagger': 8224,
  532 + 'Dagger': 8225,
  533 + 'bull': 8226,
  534 + 'hellip': 8230,
  535 + 'permil': 8240,
  536 + 'prime': 8242,
  537 + 'Prime': 8243,
  538 + 'lsaquo': 8249,
  539 + 'rsaquo': 8250,
  540 + 'oline': 8254,
  541 + 'frasl': 8260,
  542 + 'euro': 8364,
  543 + 'image': 8465,
  544 + 'weierp': 8472,
  545 + 'real': 8476,
  546 + 'trade': 8482,
  547 + 'alefsym': 8501,
  548 + 'larr': 8592,
  549 + 'uarr': 8593,
  550 + 'rarr': 8594,
  551 + 'darr': 8595,
  552 + 'harr': 8596,
  553 + 'crarr': 8629,
  554 + 'lArr': 8656,
  555 + 'uArr': 8657,
  556 + 'rArr': 8658,
  557 + 'dArr': 8659,
  558 + 'hArr': 8660,
  559 + 'forall': 8704,
  560 + 'part': 8706,
  561 + 'exist': 8707,
  562 + 'empty': 8709,
  563 + 'nabla': 8711,
  564 + 'isin': 8712,
  565 + 'notin': 8713,
  566 + 'ni': 8715,
  567 + 'prod': 8719,
  568 + 'sum': 8721,
  569 + 'minus': 8722,
  570 + 'lowast': 8727,
  571 + 'radic': 8730,
  572 + 'prop': 8733,
  573 + 'infin': 8734,
  574 + 'ang': 8736,
  575 + 'and': 8743,
  576 + 'or': 8744,
  577 + 'cap': 8745,
  578 + 'cup': 8746,
  579 + 'int': 8747,
  580 + 'there4': 8756,
  581 + 'sim': 8764,
  582 + 'cong': 8773,
  583 + 'asymp': 8776,
  584 + 'ne': 8800,
  585 + 'equiv': 8801,
  586 + 'le': 8804,
  587 + 'ge': 8805,
  588 + 'sub': 8834,
  589 + 'sup': 8835,
  590 + 'nsub': 8836,
  591 + 'sube': 8838,
  592 + 'supe': 8839,
  593 + 'oplus': 8853,
  594 + 'otimes': 8855,
  595 + 'perp': 8869,
  596 + 'sdot': 8901,
  597 + 'lceil': 8968,
  598 + 'rceil': 8969,
  599 + 'lfloor': 8970,
  600 + 'rfloor': 8971,
  601 + 'lang': 9001,
  602 + 'rang': 9002,
  603 + 'loz': 9674,
  604 + 'spades': 9824,
  605 + 'clubs': 9827,
  606 + 'hearts': 9829,
  607 + 'diams': 9830
  608 + }
  609 +
  610 + Object.keys(sax.ENTITIES).forEach(function (key) {
  611 + var e = sax.ENTITIES[key]
  612 + var s = typeof e === 'number' ? String.fromCharCode(e) : e
  613 + sax.ENTITIES[key] = s
  614 + })
  615 +
  616 + for (var s in sax.STATE) {
  617 + sax.STATE[sax.STATE[s]] = s
  618 + }
  619 +
  620 + // shorthand
  621 + S = sax.STATE
  622 +
  623 + function emit (parser, event, data) {
  624 + parser[event] && parser[event](data)
  625 + }
  626 +
  627 + function emitNode (parser, nodeType, data) {
  628 + if (parser.textNode) closeText(parser)
  629 + emit(parser, nodeType, data)
  630 + }
  631 +
  632 + function closeText (parser) {
  633 + parser.textNode = textopts(parser.opt, parser.textNode)
  634 + if (parser.textNode) emit(parser, 'ontext', parser.textNode)
  635 + parser.textNode = ''
  636 + }
  637 +
  638 + function textopts (opt, text) {
  639 + if (opt.trim) text = text.trim()
  640 + if (opt.normalize) text = text.replace(/\s+/g, ' ')
  641 + return text
  642 + }
  643 +
  644 + function error (parser, er) {
  645 + closeText(parser)
  646 + if (parser.trackPosition) {
  647 + er += '\nLine: ' + parser.line +
  648 + '\nColumn: ' + parser.column +
  649 + '\nChar: ' + parser.c
  650 + }
  651 + er = new Error(er)
  652 + parser.error = er
  653 + emit(parser, 'onerror', er)
  654 + return parser
  655 + }
  656 +
  657 + function end (parser) {
  658 + if (parser.sawRoot && !parser.closedRoot) strictFail(parser, 'Unclosed root tag')
  659 + if ((parser.state !== S.BEGIN) &&
  660 + (parser.state !== S.BEGIN_WHITESPACE) &&
  661 + (parser.state !== S.TEXT)) {
  662 + error(parser, 'Unexpected end')
  663 + }
  664 + closeText(parser)
  665 + parser.c = ''
  666 + parser.closed = true
  667 + emit(parser, 'onend')
  668 + SAXParser.call(parser, parser.strict, parser.opt)
  669 + return parser
  670 + }
  671 +
  672 + function strictFail (parser, message) {
  673 + if (typeof parser !== 'object' || !(parser instanceof SAXParser)) {
  674 + throw new Error('bad call to strictFail')
  675 + }
  676 + if (parser.strict) {
  677 + error(parser, message)
  678 + }
  679 + }
  680 +
  681 + function newTag (parser) {
  682 + if (!parser.strict) parser.tagName = parser.tagName[parser.looseCase]()
  683 + var parent = parser.tags[parser.tags.length - 1] || parser
  684 + var tag = parser.tag = { name: parser.tagName, attributes: {} }
  685 +
  686 + // will be overridden if tag contails an xmlns="foo" or xmlns:foo="bar"
  687 + if (parser.opt.xmlns) {
  688 + tag.ns = parent.ns
  689 + }
  690 + parser.attribList.length = 0
  691 + emitNode(parser, 'onopentagstart', tag)
  692 + }
  693 +
  694 + function qname (name, attribute) {
  695 + var i = name.indexOf(':')
  696 + var qualName = i < 0 ? [ '', name ] : name.split(':')
  697 + var prefix = qualName[0]
  698 + var local = qualName[1]
  699 +
  700 + // <x "xmlns"="http://foo">
  701 + if (attribute && name === 'xmlns') {
  702 + prefix = 'xmlns'
  703 + local = ''
  704 + }
  705 +
  706 + return { prefix: prefix, local: local }
  707 + }
  708 +
  709 + function attrib (parser) {
  710 + if (!parser.strict) {
  711 + parser.attribName = parser.attribName[parser.looseCase]()
  712 + }
  713 +
  714 + if (parser.attribList.indexOf(parser.attribName) !== -1 ||
  715 + parser.tag.attributes.hasOwnProperty(parser.attribName)) {
  716 + parser.attribName = parser.attribValue = ''
  717 + return
  718 + }
  719 +
  720 + if (parser.opt.xmlns) {
  721 + var qn = qname(parser.attribName, true)
  722 + var prefix = qn.prefix
  723 + var local = qn.local
  724 +
  725 + if (prefix === 'xmlns') {
  726 + // namespace binding attribute. push the binding into scope
  727 + if (local === 'xml' && parser.attribValue !== XML_NAMESPACE) {
  728 + strictFail(parser,
  729 + 'xml: prefix must be bound to ' + XML_NAMESPACE + '\n' +
  730 + 'Actual: ' + parser.attribValue)
  731 + } else if (local === 'xmlns' && parser.attribValue !== XMLNS_NAMESPACE) {
  732 + strictFail(parser,
  733 + 'xmlns: prefix must be bound to ' + XMLNS_NAMESPACE + '\n' +
  734 + 'Actual: ' + parser.attribValue)
  735 + } else {
  736 + var tag = parser.tag
  737 + var parent = parser.tags[parser.tags.length - 1] || parser
  738 + if (tag.ns === parent.ns) {
  739 + tag.ns = Object.create(parent.ns)
  740 + }
  741 + tag.ns[local] = parser.attribValue
  742 + }
  743 + }
  744 +
  745 + // defer onattribute events until all attributes have been seen
  746 + // so any new bindings can take effect. preserve attribute order
  747 + // so deferred events can be emitted in document order
  748 + parser.attribList.push([parser.attribName, parser.attribValue])
  749 + } else {
  750 + // in non-xmlns mode, we can emit the event right away
  751 + parser.tag.attributes[parser.attribName] = parser.attribValue
  752 + emitNode(parser, 'onattribute', {
  753 + name: parser.attribName,
  754 + value: parser.attribValue
  755 + })
  756 + }
  757 +
  758 + parser.attribName = parser.attribValue = ''
  759 + }
  760 +
  761 + function openTag (parser, selfClosing) {
  762 + if (parser.opt.xmlns) {
  763 + // emit namespace binding events
  764 + var tag = parser.tag
  765 +
  766 + // add namespace info to tag
  767 + var qn = qname(parser.tagName)
  768 + tag.prefix = qn.prefix
  769 + tag.local = qn.local
  770 + tag.uri = tag.ns[qn.prefix] || ''
  771 +
  772 + if (tag.prefix && !tag.uri) {
  773 + strictFail(parser, 'Unbound namespace prefix: ' +
  774 + JSON.stringify(parser.tagName))
  775 + tag.uri = qn.prefix
  776 + }
  777 +
  778 + var parent = parser.tags[parser.tags.length - 1] || parser
  779 + if (tag.ns && parent.ns !== tag.ns) {
  780 + Object.keys(tag.ns).forEach(function (p) {
  781 + emitNode(parser, 'onopennamespace', {
  782 + prefix: p,
  783 + uri: tag.ns[p]
  784 + })
  785 + })
  786 + }
  787 +
  788 + // handle deferred onattribute events
  789 + // Note: do not apply default ns to attributes:
  790 + // http://www.w3.org/TR/REC-xml-names/#defaulting
  791 + for (var i = 0, l = parser.attribList.length; i < l; i++) {
  792 + var nv = parser.attribList[i]
  793 + var name = nv[0]
  794 + var value = nv[1]
  795 + var qualName = qname(name, true)
  796 + var prefix = qualName.prefix
  797 + var local = qualName.local
  798 + var uri = prefix === '' ? '' : (tag.ns[prefix] || '')
  799 + var a = {
  800 + name: name,
  801 + value: value,
  802 + prefix: prefix,
  803 + local: local,
  804 + uri: uri
  805 + }
  806 +
  807 + // if there's any attributes with an undefined namespace,
  808 + // then fail on them now.
  809 + if (prefix && prefix !== 'xmlns' && !uri) {
  810 + strictFail(parser, 'Unbound namespace prefix: ' +
  811 + JSON.stringify(prefix))
  812 + a.uri = prefix
  813 + }
  814 + parser.tag.attributes[name] = a
  815 + emitNode(parser, 'onattribute', a)
  816 + }
  817 + parser.attribList.length = 0
  818 + }
  819 +
  820 + parser.tag.isSelfClosing = !!selfClosing
  821 +
  822 + // process the tag
  823 + parser.sawRoot = true
  824 + parser.tags.push(parser.tag)
  825 + emitNode(parser, 'onopentag', parser.tag)
  826 + if (!selfClosing) {
  827 + // special case for <script> in non-strict mode.
  828 + if (!parser.noscript && parser.tagName.toLowerCase() === 'script') {
  829 + parser.state = S.SCRIPT
  830 + } else {
  831 + parser.state = S.TEXT
  832 + }
  833 + parser.tag = null
  834 + parser.tagName = ''
  835 + }
  836 + parser.attribName = parser.attribValue = ''
  837 + parser.attribList.length = 0
  838 + }
  839 +
  840 + function closeTag (parser) {
  841 + if (!parser.tagName) {
  842 + strictFail(parser, 'Weird empty close tag.')
  843 + parser.textNode += '</>'
  844 + parser.state = S.TEXT
  845 + return
  846 + }
  847 +
  848 + if (parser.script) {
  849 + if (parser.tagName !== 'script') {
  850 + parser.script += '</' + parser.tagName + '>'
  851 + parser.tagName = ''
  852 + parser.state = S.SCRIPT
  853 + return
  854 + }
  855 + emitNode(parser, 'onscript', parser.script)
  856 + parser.script = ''
  857 + }
  858 +
  859 + // first make sure that the closing tag actually exists.
  860 + // <a><b></c></b></a> will close everything, otherwise.
  861 + var t = parser.tags.length
  862 + var tagName = parser.tagName
  863 + if (!parser.strict) {
  864 + tagName = tagName[parser.looseCase]()
  865 + }
  866 + var closeTo = tagName
  867 + while (t--) {
  868 + var close = parser.tags[t]
  869 + if (close.name !== closeTo) {
  870 + // fail the first time in strict mode
  871 + strictFail(parser, 'Unexpected close tag')
  872 + } else {
  873 + break
  874 + }
  875 + }
  876 +
  877 + // didn't find it. we already failed for strict, so just abort.
  878 + if (t < 0) {
  879 + strictFail(parser, 'Unmatched closing tag: ' + parser.tagName)
  880 + parser.textNode += '</' + parser.tagName + '>'
  881 + parser.state = S.TEXT
  882 + return
  883 + }
  884 + parser.tagName = tagName
  885 + var s = parser.tags.length
  886 + while (s-- > t) {
  887 + var tag = parser.tag = parser.tags.pop()
  888 + parser.tagName = parser.tag.name
  889 + emitNode(parser, 'onclosetag', parser.tagName)
  890 +
  891 + var x = {}
  892 + for (var i in tag.ns) {
  893 + x[i] = tag.ns[i]
  894 + }
  895 +
  896 + var parent = parser.tags[parser.tags.length - 1] || parser
  897 + if (parser.opt.xmlns && tag.ns !== parent.ns) {
  898 + // remove namespace bindings introduced by tag
  899 + Object.keys(tag.ns).forEach(function (p) {
  900 + var n = tag.ns[p]
  901 + emitNode(parser, 'onclosenamespace', { prefix: p, uri: n })
  902 + })
  903 + }
  904 + }
  905 + if (t === 0) parser.closedRoot = true
  906 + parser.tagName = parser.attribValue = parser.attribName = ''
  907 + parser.attribList.length = 0
  908 + parser.state = S.TEXT
  909 + }
  910 +
  911 + function parseEntity (parser) {
  912 + var entity = parser.entity
  913 + var entityLC = entity.toLowerCase()
  914 + var num
  915 + var numStr = ''
  916 +
  917 + if (parser.ENTITIES[entity]) {
  918 + return parser.ENTITIES[entity]
  919 + }
  920 + if (parser.ENTITIES[entityLC]) {
  921 + return parser.ENTITIES[entityLC]
  922 + }
  923 + entity = entityLC
  924 + if (entity.charAt(0) === '#') {
  925 + if (entity.charAt(1) === 'x') {
  926 + entity = entity.slice(2)
  927 + num = parseInt(entity, 16)
  928 + numStr = num.toString(16)
  929 + } else {
  930 + entity = entity.slice(1)
  931 + num = parseInt(entity, 10)
  932 + numStr = num.toString(10)
  933 + }
  934 + }
  935 + entity = entity.replace(/^0+/, '')
  936 + if (isNaN(num) || numStr.toLowerCase() !== entity) {
  937 + strictFail(parser, 'Invalid character entity')
  938 + return '&' + parser.entity + ';'
  939 + }
  940 +
  941 + return String.fromCodePoint(num)
  942 + }
  943 +
  944 + function beginWhiteSpace (parser, c) {
  945 + if (c === '<') {
  946 + parser.state = S.OPEN_WAKA
  947 + parser.startTagPosition = parser.position
  948 + } else if (!isWhitespace(c)) {
  949 + // have to process this as a text node.
  950 + // weird, but happens.
  951 + strictFail(parser, 'Non-whitespace before first tag.')
  952 + parser.textNode = c
  953 + parser.state = S.TEXT
  954 + }
  955 + }
  956 +
  957 + function charAt (chunk, i) {
  958 + var result = ''
  959 + if (i < chunk.length) {
  960 + result = chunk.charAt(i)
  961 + }
  962 + return result
  963 + }
  964 +
  965 + function write (chunk) {
  966 + var parser = this
  967 + if (this.error) {
  968 + throw this.error
  969 + }
  970 + if (parser.closed) {
  971 + return error(parser,
  972 + 'Cannot write after close. Assign an onready handler.')
  973 + }
  974 + if (chunk === null) {
  975 + return end(parser)
  976 + }
  977 + if (typeof chunk === 'object') {
  978 + chunk = chunk.toString()
  979 + }
  980 + var i = 0
  981 + var c = ''
  982 + while (true) {
  983 + c = charAt(chunk, i++)
  984 + parser.c = c
  985 +
  986 + if (!c) {
  987 + break
  988 + }
  989 +
  990 + if (parser.trackPosition) {
  991 + parser.position++
  992 + if (c === '\n') {
  993 + parser.line++
  994 + parser.column = 0
  995 + } else {
  996 + parser.column++
  997 + }
  998 + }
  999 +
  1000 + switch (parser.state) {
  1001 + case S.BEGIN:
  1002 + parser.state = S.BEGIN_WHITESPACE
  1003 + if (c === '\uFEFF') {
  1004 + continue
  1005 + }
  1006 + beginWhiteSpace(parser, c)
  1007 + continue
  1008 +
  1009 + case S.BEGIN_WHITESPACE:
  1010 + beginWhiteSpace(parser, c)
  1011 + continue
  1012 +
  1013 + case S.TEXT:
  1014 + if (parser.sawRoot && !parser.closedRoot) {
  1015 + var starti = i - 1
  1016 + while (c && c !== '<' && c !== '&') {
  1017 + c = charAt(chunk, i++)
  1018 + if (c && parser.trackPosition) {
  1019 + parser.position++
  1020 + if (c === '\n') {
  1021 + parser.line++
  1022 + parser.column = 0
  1023 + } else {
  1024 + parser.column++
  1025 + }
  1026 + }
  1027 + }
  1028 + parser.textNode += chunk.substring(starti, i - 1)
  1029 + }
  1030 + if (c === '<' && !(parser.sawRoot && parser.closedRoot && !parser.strict)) {
  1031 + parser.state = S.OPEN_WAKA
  1032 + parser.startTagPosition = parser.position
  1033 + } else {
  1034 + if (!isWhitespace(c) && (!parser.sawRoot || parser.closedRoot)) {
  1035 + strictFail(parser, 'Text data outside of root node.')
  1036 + }
  1037 + if (c === '&') {
  1038 + parser.state = S.TEXT_ENTITY
  1039 + } else {
  1040 + parser.textNode += c
  1041 + }
  1042 + }
  1043 + continue
  1044 +
  1045 + case S.SCRIPT:
  1046 + // only non-strict
  1047 + if (c === '<') {
  1048 + parser.state = S.SCRIPT_ENDING
  1049 + } else {
  1050 + parser.script += c
  1051 + }
  1052 + continue
  1053 +
  1054 + case S.SCRIPT_ENDING:
  1055 + if (c === '/') {
  1056 + parser.state = S.CLOSE_TAG
  1057 + } else {
  1058 + parser.script += '<' + c
  1059 + parser.state = S.SCRIPT
  1060 + }
  1061 + continue
  1062 +
  1063 + case S.OPEN_WAKA:
  1064 + // either a /, ?, !, or text is coming next.
  1065 + if (c === '!') {
  1066 + parser.state = S.SGML_DECL
  1067 + parser.sgmlDecl = ''
  1068 + } else if (isWhitespace(c)) {
  1069 + // wait for it...
  1070 + } else if (isMatch(nameStart, c)) {
  1071 + parser.state = S.OPEN_TAG
  1072 + parser.tagName = c
  1073 + } else if (c === '/') {
  1074 + parser.state = S.CLOSE_TAG
  1075 + parser.tagName = ''
  1076 + } else if (c === '?') {
  1077 + parser.state = S.PROC_INST
  1078 + parser.procInstName = parser.procInstBody = ''
  1079 + } else {
  1080 + strictFail(parser, 'Unencoded <')
  1081 + // if there was some whitespace, then add that in.
  1082 + if (parser.startTagPosition + 1 < parser.position) {
  1083 + var pad = parser.position - parser.startTagPosition
  1084 + c = new Array(pad).join(' ') + c
  1085 + }
  1086 + parser.textNode += '<' + c
  1087 + parser.state = S.TEXT
  1088 + }
  1089 + continue
  1090 +
  1091 + case S.SGML_DECL:
  1092 + if ((parser.sgmlDecl + c).toUpperCase() === CDATA) {
  1093 + emitNode(parser, 'onopencdata')
  1094 + parser.state = S.CDATA
  1095 + parser.sgmlDecl = ''
  1096 + parser.cdata = ''
  1097 + } else if (parser.sgmlDecl + c === '--') {
  1098 + parser.state = S.COMMENT
  1099 + parser.comment = ''
  1100 + parser.sgmlDecl = ''
  1101 + } else if ((parser.sgmlDecl + c).toUpperCase() === DOCTYPE) {
  1102 + parser.state = S.DOCTYPE
  1103 + if (parser.doctype || parser.sawRoot) {
  1104 + strictFail(parser,
  1105 + 'Inappropriately located doctype declaration')
  1106 + }
  1107 + parser.doctype = ''
  1108 + parser.sgmlDecl = ''
  1109 + } else if (c === '>') {
  1110 + emitNode(parser, 'onsgmldeclaration', parser.sgmlDecl)
  1111 + parser.sgmlDecl = ''
  1112 + parser.state = S.TEXT
  1113 + } else if (isQuote(c)) {
  1114 + parser.state = S.SGML_DECL_QUOTED
  1115 + parser.sgmlDecl += c
  1116 + } else {
  1117 + parser.sgmlDecl += c
  1118 + }
  1119 + continue
  1120 +
  1121 + case S.SGML_DECL_QUOTED:
  1122 + if (c === parser.q) {
  1123 + parser.state = S.SGML_DECL
  1124 + parser.q = ''
  1125 + }
  1126 + parser.sgmlDecl += c
  1127 + continue
  1128 +
  1129 + case S.DOCTYPE:
  1130 + if (c === '>') {
  1131 + parser.state = S.TEXT
  1132 + emitNode(parser, 'ondoctype', parser.doctype)
  1133 + parser.doctype = true // just remember that we saw it.
  1134 + } else {
  1135 + parser.doctype += c
  1136 + if (c === '[') {
  1137 + parser.state = S.DOCTYPE_DTD
  1138 + } else if (isQuote(c)) {
  1139 + parser.state = S.DOCTYPE_QUOTED
  1140 + parser.q = c
  1141 + }
  1142 + }
  1143 + continue
  1144 +
  1145 + case S.DOCTYPE_QUOTED:
  1146 + parser.doctype += c
  1147 + if (c === parser.q) {
  1148 + parser.q = ''
  1149 + parser.state = S.DOCTYPE
  1150 + }
  1151 + continue
  1152 +
  1153 + case S.DOCTYPE_DTD:
  1154 + parser.doctype += c
  1155 + if (c === ']') {
  1156 + parser.state = S.DOCTYPE
  1157 + } else if (isQuote(c)) {
  1158 + parser.state = S.DOCTYPE_DTD_QUOTED
  1159 + parser.q = c
  1160 + }
  1161 + continue
  1162 +
  1163 + case S.DOCTYPE_DTD_QUOTED:
  1164 + parser.doctype += c
  1165 + if (c === parser.q) {
  1166 + parser.state = S.DOCTYPE_DTD
  1167 + parser.q = ''
  1168 + }
  1169 + continue
  1170 +
  1171 + case S.COMMENT:
  1172 + if (c === '-') {
  1173 + parser.state = S.COMMENT_ENDING
  1174 + } else {
  1175 + parser.comment += c
  1176 + }
  1177 + continue
  1178 +
  1179 + case S.COMMENT_ENDING:
  1180 + if (c === '-') {
  1181 + parser.state = S.COMMENT_ENDED
  1182 + parser.comment = textopts(parser.opt, parser.comment)
  1183 + if (parser.comment) {
  1184 + emitNode(parser, 'oncomment', parser.comment)
  1185 + }
  1186 + parser.comment = ''
  1187 + } else {
  1188 + parser.comment += '-' + c
  1189 + parser.state = S.COMMENT
  1190 + }
  1191 + continue
  1192 +
  1193 + case S.COMMENT_ENDED:
  1194 + if (c !== '>') {
  1195 + strictFail(parser, 'Malformed comment')
  1196 + // allow <!-- blah -- bloo --> in non-strict mode,
  1197 + // which is a comment of " blah -- bloo "
  1198 + parser.comment += '--' + c
  1199 + parser.state = S.COMMENT
  1200 + } else {
  1201 + parser.state = S.TEXT
  1202 + }
  1203 + continue
  1204 +
  1205 + case S.CDATA:
  1206 + if (c === ']') {
  1207 + parser.state = S.CDATA_ENDING
  1208 + } else {
  1209 + parser.cdata += c
  1210 + }
  1211 + continue
  1212 +
  1213 + case S.CDATA_ENDING:
  1214 + if (c === ']') {
  1215 + parser.state = S.CDATA_ENDING_2
  1216 + } else {
  1217 + parser.cdata += ']' + c
  1218 + parser.state = S.CDATA
  1219 + }
  1220 + continue
  1221 +
  1222 + case S.CDATA_ENDING_2:
  1223 + if (c === '>') {
  1224 + if (parser.cdata) {
  1225 + emitNode(parser, 'oncdata', parser.cdata)
  1226 + }
  1227 + emitNode(parser, 'onclosecdata')
  1228 + parser.cdata = ''
  1229 + parser.state = S.TEXT
  1230 + } else if (c === ']') {
  1231 + parser.cdata += ']'
  1232 + } else {
  1233 + parser.cdata += ']]' + c
  1234 + parser.state = S.CDATA
  1235 + }
  1236 + continue
  1237 +
  1238 + case S.PROC_INST:
  1239 + if (c === '?') {
  1240 + parser.state = S.PROC_INST_ENDING
  1241 + } else if (isWhitespace(c)) {
  1242 + parser.state = S.PROC_INST_BODY
  1243 + } else {
  1244 + parser.procInstName += c
  1245 + }
  1246 + continue
  1247 +
  1248 + case S.PROC_INST_BODY:
  1249 + if (!parser.procInstBody && isWhitespace(c)) {
  1250 + continue
  1251 + } else if (c === '?') {
  1252 + parser.state = S.PROC_INST_ENDING
  1253 + } else {
  1254 + parser.procInstBody += c
  1255 + }
  1256 + continue
  1257 +
  1258 + case S.PROC_INST_ENDING:
  1259 + if (c === '>') {
  1260 + emitNode(parser, 'onprocessinginstruction', {
  1261 + name: parser.procInstName,
  1262 + body: parser.procInstBody
  1263 + })
  1264 + parser.procInstName = parser.procInstBody = ''
  1265 + parser.state = S.TEXT
  1266 + } else {
  1267 + parser.procInstBody += '?' + c
  1268 + parser.state = S.PROC_INST_BODY
  1269 + }
  1270 + continue
  1271 +
  1272 + case S.OPEN_TAG:
  1273 + if (isMatch(nameBody, c)) {
  1274 + parser.tagName += c
  1275 + } else {
  1276 + newTag(parser)
  1277 + if (c === '>') {
  1278 + openTag(parser)
  1279 + } else if (c === '/') {
  1280 + parser.state = S.OPEN_TAG_SLASH
  1281 + } else {
  1282 + if (!isWhitespace(c)) {
  1283 + strictFail(parser, 'Invalid character in tag name')
  1284 + }
  1285 + parser.state = S.ATTRIB
  1286 + }
  1287 + }
  1288 + continue
  1289 +
  1290 + case S.OPEN_TAG_SLASH:
  1291 + if (c === '>') {
  1292 + openTag(parser, true)
  1293 + closeTag(parser)
  1294 + } else {
  1295 + strictFail(parser, 'Forward-slash in opening tag not followed by >')
  1296 + parser.state = S.ATTRIB
  1297 + }
  1298 + continue
  1299 +
  1300 + case S.ATTRIB:
  1301 + // haven't read the attribute name yet.
  1302 + if (isWhitespace(c)) {
  1303 + continue
  1304 + } else if (c === '>') {
  1305 + openTag(parser)
  1306 + } else if (c === '/') {
  1307 + parser.state = S.OPEN_TAG_SLASH
  1308 + } else if (isMatch(nameStart, c)) {
  1309 + parser.attribName = c
  1310 + parser.attribValue = ''
  1311 + parser.state = S.ATTRIB_NAME
  1312 + } else {
  1313 + strictFail(parser, 'Invalid attribute name')
  1314 + }
  1315 + continue
  1316 +
  1317 + case S.ATTRIB_NAME:
  1318 + if (c === '=') {
  1319 + parser.state = S.ATTRIB_VALUE
  1320 + } else if (c === '>') {
  1321 + strictFail(parser, 'Attribute without value')
  1322 + parser.attribValue = parser.attribName
  1323 + attrib(parser)
  1324 + openTag(parser)
  1325 + } else if (isWhitespace(c)) {
  1326 + parser.state = S.ATTRIB_NAME_SAW_WHITE
  1327 + } else if (isMatch(nameBody, c)) {
  1328 + parser.attribName += c
  1329 + } else {
  1330 + strictFail(parser, 'Invalid attribute name')
  1331 + }
  1332 + continue
  1333 +
  1334 + case S.ATTRIB_NAME_SAW_WHITE:
  1335 + if (c === '=') {
  1336 + parser.state = S.ATTRIB_VALUE
  1337 + } else if (isWhitespace(c)) {
  1338 + continue
  1339 + } else {
  1340 + strictFail(parser, 'Attribute without value')
  1341 + parser.tag.attributes[parser.attribName] = ''
  1342 + parser.attribValue = ''
  1343 + emitNode(parser, 'onattribute', {
  1344 + name: parser.attribName,
  1345 + value: ''
  1346 + })
  1347 + parser.attribName = ''
  1348 + if (c === '>') {
  1349 + openTag(parser)
  1350 + } else if (isMatch(nameStart, c)) {
  1351 + parser.attribName = c
  1352 + parser.state = S.ATTRIB_NAME
  1353 + } else {
  1354 + strictFail(parser, 'Invalid attribute name')
  1355 + parser.state = S.ATTRIB
  1356 + }
  1357 + }
  1358 + continue
  1359 +
  1360 + case S.ATTRIB_VALUE:
  1361 + if (isWhitespace(c)) {
  1362 + continue
  1363 + } else if (isQuote(c)) {
  1364 + parser.q = c
  1365 + parser.state = S.ATTRIB_VALUE_QUOTED
  1366 + } else {
  1367 + strictFail(parser, 'Unquoted attribute value')
  1368 + parser.state = S.ATTRIB_VALUE_UNQUOTED
  1369 + parser.attribValue = c
  1370 + }
  1371 + continue
  1372 +
  1373 + case S.ATTRIB_VALUE_QUOTED:
  1374 + if (c !== parser.q) {
  1375 + if (c === '&') {
  1376 + parser.state = S.ATTRIB_VALUE_ENTITY_Q
  1377 + } else {
  1378 + parser.attribValue += c
  1379 + }
  1380 + continue
  1381 + }
  1382 + attrib(parser)
  1383 + parser.q = ''
  1384 + parser.state = S.ATTRIB_VALUE_CLOSED
  1385 + continue
  1386 +
  1387 + case S.ATTRIB_VALUE_CLOSED:
  1388 + if (isWhitespace(c)) {
  1389 + parser.state = S.ATTRIB
  1390 + } else if (c === '>') {
  1391 + openTag(parser)
  1392 + } else if (c === '/') {
  1393 + parser.state = S.OPEN_TAG_SLASH
  1394 + } else if (isMatch(nameStart, c)) {
  1395 + strictFail(parser, 'No whitespace between attributes')
  1396 + parser.attribName = c
  1397 + parser.attribValue = ''
  1398 + parser.state = S.ATTRIB_NAME
  1399 + } else {
  1400 + strictFail(parser, 'Invalid attribute name')
  1401 + }
  1402 + continue
  1403 +
  1404 + case S.ATTRIB_VALUE_UNQUOTED:
  1405 + if (!isAttribEnd(c)) {
  1406 + if (c === '&') {
  1407 + parser.state = S.ATTRIB_VALUE_ENTITY_U
  1408 + } else {
  1409 + parser.attribValue += c
  1410 + }
  1411 + continue
  1412 + }
  1413 + attrib(parser)
  1414 + if (c === '>') {
  1415 + openTag(parser)
  1416 + } else {
  1417 + parser.state = S.ATTRIB
  1418 + }
  1419 + continue
  1420 +
  1421 + case S.CLOSE_TAG:
  1422 + if (!parser.tagName) {
  1423 + if (isWhitespace(c)) {
  1424 + continue
  1425 + } else if (notMatch(nameStart, c)) {
  1426 + if (parser.script) {
  1427 + parser.script += '</' + c
  1428 + parser.state = S.SCRIPT
  1429 + } else {
  1430 + strictFail(parser, 'Invalid tagname in closing tag.')
  1431 + }
  1432 + } else {
  1433 + parser.tagName = c
  1434 + }
  1435 + } else if (c === '>') {
  1436 + closeTag(parser)
  1437 + } else if (isMatch(nameBody, c)) {
  1438 + parser.tagName += c
  1439 + } else if (parser.script) {
  1440 + parser.script += '</' + parser.tagName
  1441 + parser.tagName = ''
  1442 + parser.state = S.SCRIPT
  1443 + } else {
  1444 + if (!isWhitespace(c)) {
  1445 + strictFail(parser, 'Invalid tagname in closing tag')
  1446 + }
  1447 + parser.state = S.CLOSE_TAG_SAW_WHITE
  1448 + }
  1449 + continue
  1450 +
  1451 + case S.CLOSE_TAG_SAW_WHITE:
  1452 + if (isWhitespace(c)) {
  1453 + continue
  1454 + }
  1455 + if (c === '>') {
  1456 + closeTag(parser)
  1457 + } else {
  1458 + strictFail(parser, 'Invalid characters in closing tag')
  1459 + }
  1460 + continue
  1461 +
  1462 + case S.TEXT_ENTITY:
  1463 + case S.ATTRIB_VALUE_ENTITY_Q:
  1464 + case S.ATTRIB_VALUE_ENTITY_U:
  1465 + var returnState
  1466 + var buffer
  1467 + switch (parser.state) {
  1468 + case S.TEXT_ENTITY:
  1469 + returnState = S.TEXT
  1470 + buffer = 'textNode'
  1471 + break
  1472 +
  1473 + case S.ATTRIB_VALUE_ENTITY_Q:
  1474 + returnState = S.ATTRIB_VALUE_QUOTED
  1475 + buffer = 'attribValue'
  1476 + break
  1477 +
  1478 + case S.ATTRIB_VALUE_ENTITY_U:
  1479 + returnState = S.ATTRIB_VALUE_UNQUOTED
  1480 + buffer = 'attribValue'
  1481 + break
  1482 + }
  1483 +
  1484 + if (c === ';') {
  1485 + parser[buffer] += parseEntity(parser)
  1486 + parser.entity = ''
  1487 + parser.state = returnState
  1488 + } else if (isMatch(parser.entity.length ? entityBody : entityStart, c)) {
  1489 + parser.entity += c
  1490 + } else {
  1491 + strictFail(parser, 'Invalid character in entity name')
  1492 + parser[buffer] += '&' + parser.entity + c
  1493 + parser.entity = ''
  1494 + parser.state = returnState
  1495 + }
  1496 +
  1497 + continue
  1498 +
  1499 + default:
  1500 + throw new Error(parser, 'Unknown state: ' + parser.state)
  1501 + }
  1502 + } // while
  1503 +
  1504 + if (parser.position >= parser.bufferCheckPosition) {
  1505 + checkBufferLength(parser)
  1506 + }
  1507 + return parser
  1508 + }
  1509 +
  1510 + /*! http://mths.be/fromcodepoint v0.1.0 by @mathias */
  1511 + /* istanbul ignore next */
  1512 + if (!String.fromCodePoint) {
  1513 + (function () {
  1514 + var stringFromCharCode = String.fromCharCode
  1515 + var floor = Math.floor
  1516 + var fromCodePoint = function () {
  1517 + var MAX_SIZE = 0x4000
  1518 + var codeUnits = []
  1519 + var highSurrogate
  1520 + var lowSurrogate
  1521 + var index = -1
  1522 + var length = arguments.length
  1523 + if (!length) {
  1524 + return ''
  1525 + }
  1526 + var result = ''
  1527 + while (++index < length) {
  1528 + var codePoint = Number(arguments[index])
  1529 + if (
  1530 + !isFinite(codePoint) || // `NaN`, `+Infinity`, or `-Infinity`
  1531 + codePoint < 0 || // not a valid Unicode code point
  1532 + codePoint > 0x10FFFF || // not a valid Unicode code point
  1533 + floor(codePoint) !== codePoint // not an integer
  1534 + ) {
  1535 + throw RangeError('Invalid code point: ' + codePoint)
  1536 + }
  1537 + if (codePoint <= 0xFFFF) { // BMP code point
  1538 + codeUnits.push(codePoint)
  1539 + } else { // Astral code point; split in surrogate halves
  1540 + // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
  1541 + codePoint -= 0x10000
  1542 + highSurrogate = (codePoint >> 10) + 0xD800
  1543 + lowSurrogate = (codePoint % 0x400) + 0xDC00
  1544 + codeUnits.push(highSurrogate, lowSurrogate)
  1545 + }
  1546 + if (index + 1 === length || codeUnits.length > MAX_SIZE) {
  1547 + result += stringFromCharCode.apply(null, codeUnits)
  1548 + codeUnits.length = 0
  1549 + }
  1550 + }
  1551 + return result
  1552 + }
  1553 + /* istanbul ignore next */
  1554 + if (Object.defineProperty) {
  1555 + Object.defineProperty(String, 'fromCodePoint', {
  1556 + value: fromCodePoint,
  1557 + configurable: true,
  1558 + writable: true
  1559 + })
  1560 + } else {
  1561 + String.fromCodePoint = fromCodePoint
  1562 + }
  1563 + }())
  1564 + }
  1565 +})(typeof exports === 'undefined' ? this.sax = {} : exports)
  1 +{
  2 + "_args": [
  3 + [
  4 + {
  5 + "raw": "sax@>=0.6.0",
  6 + "scope": null,
  7 + "escapedName": "sax",
  8 + "name": "sax",
  9 + "rawSpec": ">=0.6.0",
  10 + "spec": ">=0.6.0",
  11 + "type": "range"
  12 + },
  13 + "/Users/fzy/project/koa2_Sequelize_project/node_modules/xml2js"
  14 + ]
  15 + ],
  16 + "_from": "sax@>=0.6.0",
  17 + "_id": "sax@1.2.4",
  18 + "_inCache": true,
  19 + "_location": "/sax",
  20 + "_nodeVersion": "8.0.0",
  21 + "_npmOperationalInternal": {
  22 + "host": "s3://npm-registry-packages",
  23 + "tmp": "tmp/sax-1.2.4.tgz_1498153598031_0.6106507133226842"
  24 + },
  25 + "_npmUser": {
  26 + "name": "isaacs",
  27 + "email": "i@izs.me"
  28 + },
  29 + "_npmVersion": "5.0.3",
  30 + "_phantomChildren": {},
  31 + "_requested": {
  32 + "raw": "sax@>=0.6.0",
  33 + "scope": null,
  34 + "escapedName": "sax",
  35 + "name": "sax",
  36 + "rawSpec": ">=0.6.0",
  37 + "spec": ">=0.6.0",
  38 + "type": "range"
  39 + },
  40 + "_requiredBy": [
  41 + "/xml2js"
  42 + ],
  43 + "_resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
  44 + "_shasum": "2816234e2378bddc4e5354fab5caa895df7100d9",
  45 + "_shrinkwrap": null,
  46 + "_spec": "sax@>=0.6.0",
  47 + "_where": "/Users/fzy/project/koa2_Sequelize_project/node_modules/xml2js",
  48 + "author": {
  49 + "name": "Isaac Z. Schlueter",
  50 + "email": "i@izs.me",
  51 + "url": "http://blog.izs.me/"
  52 + },
  53 + "bugs": {
  54 + "url": "https://github.com/isaacs/sax-js/issues"
  55 + },
  56 + "contributors": [
  57 + {
  58 + "name": "Isaac Z. Schlueter",
  59 + "email": "i@izs.me"
  60 + },
  61 + {
  62 + "name": "Stein Martin Hustad",
  63 + "email": "stein@hustad.com"
  64 + },
  65 + {
  66 + "name": "Mikeal Rogers",
  67 + "email": "mikeal.rogers@gmail.com"
  68 + },
  69 + {
  70 + "name": "Laurie Harper",
  71 + "email": "laurie@holoweb.net"
  72 + },
  73 + {
  74 + "name": "Jann Horn",
  75 + "email": "jann@Jann-PC.fritz.box"
  76 + },
  77 + {
  78 + "name": "Elijah Insua",
  79 + "email": "tmpvar@gmail.com"
  80 + },
  81 + {
  82 + "name": "Henry Rawas",
  83 + "email": "henryr@schakra.com"
  84 + },
  85 + {
  86 + "name": "Justin Makeig",
  87 + "email": "jmpublic@makeig.com"
  88 + },
  89 + {
  90 + "name": "Mike Schilling",
  91 + "email": "mike@emotive.com"
  92 + }
  93 + ],
  94 + "dependencies": {},
  95 + "description": "An evented streaming XML parser in JavaScript",
  96 + "devDependencies": {
  97 + "standard": "^8.6.0",
  98 + "tap": "^10.5.1"
  99 + },
  100 + "directories": {},
  101 + "dist": {
  102 + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
  103 + "shasum": "2816234e2378bddc4e5354fab5caa895df7100d9",
  104 + "tarball": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz"
  105 + },
  106 + "files": [
  107 + "lib/sax.js",
  108 + "LICENSE",
  109 + "README.md"
  110 + ],
  111 + "gitHead": "5aee2163d55cff24b817bbf550bac44841f9df45",
  112 + "homepage": "https://github.com/isaacs/sax-js#readme",
  113 + "license": "ISC",
  114 + "main": "lib/sax.js",
  115 + "maintainers": [
  116 + {
  117 + "name": "isaacs",
  118 + "email": "i@izs.me"
  119 + }
  120 + ],
  121 + "name": "sax",
  122 + "optionalDependencies": {},
  123 + "readme": "# sax js\n\nA sax-style parser for XML and HTML.\n\nDesigned with [node](http://nodejs.org/) in mind, but should work fine in\nthe browser or other CommonJS implementations.\n\n## What This Is\n\n* A very simple tool to parse through an XML string.\n* A stepping stone to a streaming HTML parser.\n* A handy way to deal with RSS and other mostly-ok-but-kinda-broken XML\n docs.\n\n## What This Is (probably) Not\n\n* An HTML Parser - That's a fine goal, but this isn't it. It's just\n XML.\n* A DOM Builder - You can use it to build an object model out of XML,\n but it doesn't do that out of the box.\n* XSLT - No DOM = no querying.\n* 100% Compliant with (some other SAX implementation) - Most SAX\n implementations are in Java and do a lot more than this does.\n* An XML Validator - It does a little validation when in strict mode, but\n not much.\n* A Schema-Aware XSD Thing - Schemas are an exercise in fetishistic\n masochism.\n* A DTD-aware Thing - Fetching DTDs is a much bigger job.\n\n## Regarding `<!DOCTYPE`s and `<!ENTITY`s\n\nThe parser will handle the basic XML entities in text nodes and attribute\nvalues: `&amp; &lt; &gt; &apos; &quot;`. It's possible to define additional\nentities in XML by putting them in the DTD. This parser doesn't do anything\nwith that. If you want to listen to the `ondoctype` event, and then fetch\nthe doctypes, and read the entities and add them to `parser.ENTITIES`, then\nbe my guest.\n\nUnknown entities will fail in strict mode, and in loose mode, will pass\nthrough unmolested.\n\n## Usage\n\n```javascript\nvar sax = require(\"./lib/sax\"),\n strict = true, // set to false for html-mode\n parser = sax.parser(strict);\n\nparser.onerror = function (e) {\n // an error happened.\n};\nparser.ontext = function (t) {\n // got some text. t is the string of text.\n};\nparser.onopentag = function (node) {\n // opened a tag. node has \"name\" and \"attributes\"\n};\nparser.onattribute = function (attr) {\n // an attribute. attr has \"name\" and \"value\"\n};\nparser.onend = function () {\n // parser stream is done, and ready to have more stuff written to it.\n};\n\nparser.write('<xml>Hello, <who name=\"world\">world</who>!</xml>').close();\n\n// stream usage\n// takes the same options as the parser\nvar saxStream = require(\"sax\").createStream(strict, options)\nsaxStream.on(\"error\", function (e) {\n // unhandled errors will throw, since this is a proper node\n // event emitter.\n console.error(\"error!\", e)\n // clear the error\n this._parser.error = null\n this._parser.resume()\n})\nsaxStream.on(\"opentag\", function (node) {\n // same object as above\n})\n// pipe is supported, and it's readable/writable\n// same chunks coming in also go out.\nfs.createReadStream(\"file.xml\")\n .pipe(saxStream)\n .pipe(fs.createWriteStream(\"file-copy.xml\"))\n```\n\n\n## Arguments\n\nPass the following arguments to the parser function. All are optional.\n\n`strict` - Boolean. Whether or not to be a jerk. Default: `false`.\n\n`opt` - Object bag of settings regarding string formatting. All default to `false`.\n\nSettings supported:\n\n* `trim` - Boolean. Whether or not to trim text and comment nodes.\n* `normalize` - Boolean. If true, then turn any whitespace into a single\n space.\n* `lowercase` - Boolean. If true, then lowercase tag names and attribute names\n in loose mode, rather than uppercasing them.\n* `xmlns` - Boolean. If true, then namespaces are supported.\n* `position` - Boolean. If false, then don't track line/col/position.\n* `strictEntities` - Boolean. If true, only parse [predefined XML\n entities](http://www.w3.org/TR/REC-xml/#sec-predefined-ent)\n (`&amp;`, `&apos;`, `&gt;`, `&lt;`, and `&quot;`)\n\n## Methods\n\n`write` - Write bytes onto the stream. You don't have to do this all at\nonce. You can keep writing as much as you want.\n\n`close` - Close the stream. Once closed, no more data may be written until\nit is done processing the buffer, which is signaled by the `end` event.\n\n`resume` - To gracefully handle errors, assign a listener to the `error`\nevent. Then, when the error is taken care of, you can call `resume` to\ncontinue parsing. Otherwise, the parser will not continue while in an error\nstate.\n\n## Members\n\nAt all times, the parser object will have the following members:\n\n`line`, `column`, `position` - Indications of the position in the XML\ndocument where the parser currently is looking.\n\n`startTagPosition` - Indicates the position where the current tag starts.\n\n`closed` - Boolean indicating whether or not the parser can be written to.\nIf it's `true`, then wait for the `ready` event to write again.\n\n`strict` - Boolean indicating whether or not the parser is a jerk.\n\n`opt` - Any options passed into the constructor.\n\n`tag` - The current tag being dealt with.\n\nAnd a bunch of other stuff that you probably shouldn't touch.\n\n## Events\n\nAll events emit with a single argument. To listen to an event, assign a\nfunction to `on<eventname>`. Functions get executed in the this-context of\nthe parser object. The list of supported events are also in the exported\n`EVENTS` array.\n\nWhen using the stream interface, assign handlers using the EventEmitter\n`on` function in the normal fashion.\n\n`error` - Indication that something bad happened. The error will be hanging\nout on `parser.error`, and must be deleted before parsing can continue. By\nlistening to this event, you can keep an eye on that kind of stuff. Note:\nthis happens *much* more in strict mode. Argument: instance of `Error`.\n\n`text` - Text node. Argument: string of text.\n\n`doctype` - The `<!DOCTYPE` declaration. Argument: doctype string.\n\n`processinginstruction` - Stuff like `<?xml foo=\"blerg\" ?>`. Argument:\nobject with `name` and `body` members. Attributes are not parsed, as\nprocessing instructions have implementation dependent semantics.\n\n`sgmldeclaration` - Random SGML declarations. Stuff like `<!ENTITY p>`\nwould trigger this kind of event. This is a weird thing to support, so it\nmight go away at some point. SAX isn't intended to be used to parse SGML,\nafter all.\n\n`opentagstart` - Emitted immediately when the tag name is available,\nbut before any attributes are encountered. Argument: object with a\n`name` field and an empty `attributes` set. Note that this is the\nsame object that will later be emitted in the `opentag` event.\n\n`opentag` - An opening tag. Argument: object with `name` and `attributes`.\nIn non-strict mode, tag names are uppercased, unless the `lowercase`\noption is set. If the `xmlns` option is set, then it will contain\nnamespace binding information on the `ns` member, and will have a\n`local`, `prefix`, and `uri` member.\n\n`closetag` - A closing tag. In loose mode, tags are auto-closed if their\nparent closes. In strict mode, well-formedness is enforced. Note that\nself-closing tags will have `closeTag` emitted immediately after `openTag`.\nArgument: tag name.\n\n`attribute` - An attribute node. Argument: object with `name` and `value`.\nIn non-strict mode, attribute names are uppercased, unless the `lowercase`\noption is set. If the `xmlns` option is set, it will also contains namespace\ninformation.\n\n`comment` - A comment node. Argument: the string of the comment.\n\n`opencdata` - The opening tag of a `<![CDATA[` block.\n\n`cdata` - The text of a `<![CDATA[` block. Since `<![CDATA[` blocks can get\nquite large, this event may fire multiple times for a single block, if it\nis broken up into multiple `write()`s. Argument: the string of random\ncharacter data.\n\n`closecdata` - The closing tag (`]]>`) of a `<![CDATA[` block.\n\n`opennamespace` - If the `xmlns` option is set, then this event will\nsignal the start of a new namespace binding.\n\n`closenamespace` - If the `xmlns` option is set, then this event will\nsignal the end of a namespace binding.\n\n`end` - Indication that the closed stream has ended.\n\n`ready` - Indication that the stream has reset, and is ready to be written\nto.\n\n`noscript` - In non-strict mode, `<script>` tags trigger a `\"script\"`\nevent, and their contents are not checked for special xml characters.\nIf you pass `noscript: true`, then this behavior is suppressed.\n\n## Reporting Problems\n\nIt's best to write a failing test if you find an issue. I will always\naccept pull requests with failing tests if they demonstrate intended\nbehavior, but it is very hard to figure out what issue you're describing\nwithout a test. Writing a test is also the best way for you yourself\nto figure out if you really understand the issue you think you have with\nsax-js.\n",
  124 + "readmeFilename": "README.md",
  125 + "repository": {
  126 + "type": "git",
  127 + "url": "git://github.com/isaacs/sax-js.git"
  128 + },
  129 + "scripts": {
  130 + "postpublish": "git push origin --all; git push origin --tags",
  131 + "posttest": "standard -F test/*.js lib/*.js",
  132 + "postversion": "npm publish",
  133 + "preversion": "npm test",
  134 + "test": "tap test/*.js --cov -j4"
  135 + },
  136 + "version": "1.2.4"
  137 +}
  1 +Copyright 2010, 2011, 2012, 2013. All rights reserved.
  2 +
  3 +Permission is hereby granted, free of charge, to any person obtaining a copy
  4 +of this software and associated documentation files (the "Software"), to
  5 +deal in the Software without restriction, including without limitation the
  6 +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  7 +sell copies of the Software, and to permit persons to whom the Software is
  8 +furnished to do so, subject to the following conditions:
  9 +
  10 +The above copyright notice and this permission notice shall be included in
  11 +all copies or substantial portions of the Software.
  12 +
  13 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  18 +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  19 +IN THE SOFTWARE.
  1 +node-xml2js
  2 +===========
  3 +
  4 +Ever had the urge to parse XML? And wanted to access the data in some sane,
  5 +easy way? Don't want to compile a C parser, for whatever reason? Then xml2js is
  6 +what you're looking for!
  7 +
  8 +Description
  9 +===========
  10 +
  11 +Simple XML to JavaScript object converter. It supports bi-directional conversion.
  12 +Uses [sax-js](https://github.com/isaacs/sax-js/) and
  13 +[xmlbuilder-js](https://github.com/oozcitak/xmlbuilder-js/).
  14 +
  15 +Note: If you're looking for a full DOM parser, you probably want
  16 +[JSDom](https://github.com/tmpvar/jsdom).
  17 +
  18 +Installation
  19 +============
  20 +
  21 +Simplest way to install `xml2js` is to use [npm](http://npmjs.org), just `npm
  22 +install xml2js` which will download xml2js and all dependencies.
  23 +
  24 +xml2js is also available via [Bower](http://bower.io/), just `bower install
  25 +xml2js` which will download xml2js and all dependencies.
  26 +
  27 +Usage
  28 +=====
  29 +
  30 +No extensive tutorials required because you are a smart developer! The task of
  31 +parsing XML should be an easy one, so let's make it so! Here's some examples.
  32 +
  33 +Shoot-and-forget usage
  34 +----------------------
  35 +
  36 +You want to parse XML as simple and easy as possible? It's dangerous to go
  37 +alone, take this:
  38 +
  39 +```javascript
  40 +var parseString = require('xml2js').parseString;
  41 +var xml = "<root>Hello xml2js!</root>"
  42 +parseString(xml, function (err, result) {
  43 + console.dir(result);
  44 +});
  45 +```
  46 +
  47 +Can't get easier than this, right? This works starting with `xml2js` 0.2.3.
  48 +With CoffeeScript it looks like this:
  49 +
  50 +```coffeescript
  51 +{parseString} = require 'xml2js'
  52 +xml = "<root>Hello xml2js!</root>"
  53 +parseString xml, (err, result) ->
  54 + console.dir result
  55 +```
  56 +
  57 +If you need some special options, fear not, `xml2js` supports a number of
  58 +options (see below), you can specify these as second argument:
  59 +
  60 +```javascript
  61 +parseString(xml, {trim: true}, function (err, result) {
  62 +});
  63 +```
  64 +
  65 +Simple as pie usage
  66 +-------------------
  67 +
  68 +That's right, if you have been using xml-simple or a home-grown
  69 +wrapper, this was added in 0.1.11 just for you:
  70 +
  71 +```javascript
  72 +var fs = require('fs'),
  73 + xml2js = require('xml2js');
  74 +
  75 +var parser = new xml2js.Parser();
  76 +fs.readFile(__dirname + '/foo.xml', function(err, data) {
  77 + parser.parseString(data, function (err, result) {
  78 + console.dir(result);
  79 + console.log('Done');
  80 + });
  81 +});
  82 +```
  83 +
  84 +Look ma, no event listeners!
  85 +
  86 +You can also use `xml2js` from
  87 +[CoffeeScript](https://github.com/jashkenas/coffeescript), further reducing
  88 +the clutter:
  89 +
  90 +```coffeescript
  91 +fs = require 'fs',
  92 +xml2js = require 'xml2js'
  93 +
  94 +parser = new xml2js.Parser()
  95 +fs.readFile __dirname + '/foo.xml', (err, data) ->
  96 + parser.parseString data, (err, result) ->
  97 + console.dir result
  98 + console.log 'Done.'
  99 +```
  100 +
  101 +But what happens if you forget the `new` keyword to create a new `Parser`? In
  102 +the middle of a nightly coding session, it might get lost, after all. Worry
  103 +not, we got you covered! Starting with 0.2.8 you can also leave it out, in
  104 +which case `xml2js` will helpfully add it for you, no bad surprises and
  105 +inexplicable bugs!
  106 +
  107 +Parsing multiple files
  108 +----------------------
  109 +
  110 +If you want to parse multiple files, you have multiple possibilities:
  111 +
  112 + * You can create one `xml2js.Parser` per file. That's the recommended one
  113 + and is promised to always *just work*.
  114 + * You can call `reset()` on your parser object.
  115 + * You can hope everything goes well anyway. This behaviour is not
  116 + guaranteed work always, if ever. Use option #1 if possible. Thanks!
  117 +
  118 +So you wanna some JSON?
  119 +-----------------------
  120 +
  121 +Just wrap the `result` object in a call to `JSON.stringify` like this
  122 +`JSON.stringify(result)`. You get a string containing the JSON representation
  123 +of the parsed object that you can feed to JSON-hungry consumers.
  124 +
  125 +Displaying results
  126 +------------------
  127 +
  128 +You might wonder why, using `console.dir` or `console.log` the output at some
  129 +level is only `[Object]`. Don't worry, this is not because `xml2js` got lazy.
  130 +That's because Node uses `util.inspect` to convert the object into strings and
  131 +that function stops after `depth=2` which is a bit low for most XML.
  132 +
  133 +To display the whole deal, you can use `console.log(util.inspect(result, false,
  134 +null))`, which displays the whole result.
  135 +
  136 +So much for that, but what if you use
  137 +[eyes](https://github.com/cloudhead/eyes.js) for nice colored output and it
  138 +truncates the output with `…`? Don't fear, there's also a solution for that,
  139 +you just need to increase the `maxLength` limit by creating a custom inspector
  140 +`var inspect = require('eyes').inspector({maxLength: false})` and then you can
  141 +easily `inspect(result)`.
  142 +
  143 +XML builder usage
  144 +-----------------
  145 +
  146 +Since 0.4.0, objects can be also be used to build XML:
  147 +
  148 +```javascript
  149 +var fs = require('fs'),
  150 + xml2js = require('xml2js');
  151 +
  152 +var obj = {name: "Super", Surname: "Man", age: 23};
  153 +
  154 +var builder = new xml2js.Builder();
  155 +var xml = builder.buildObject(obj);
  156 +```
  157 +
  158 +At the moment, a one to one bi-directional conversion is guaranteed only for
  159 +default configuration, except for `attrkey`, `charkey` and `explicitArray` options
  160 +you can redefine to your taste. Writing CDATA is supported via setting the `cdata`
  161 +option to `true`.
  162 +
  163 +Processing attribute, tag names and values
  164 +------------------------------------------
  165 +
  166 +Since 0.4.1 you can optionally provide the parser with attribute name and tag name processors as well as element value processors (Since 0.4.14, you can also optionally provide the parser with attribute value processors):
  167 +
  168 +```javascript
  169 +
  170 +function nameToUpperCase(name){
  171 + return name.toUpperCase();
  172 +}
  173 +
  174 +//transform all attribute and tag names and values to uppercase
  175 +parseString(xml, {
  176 + tagNameProcessors: [nameToUpperCase],
  177 + attrNameProcessors: [nameToUpperCase],
  178 + valueProcessors: [nameToUpperCase],
  179 + attrValueProcessors: [nameToUpperCase]},
  180 + function (err, result) {
  181 + // processed data
  182 +});
  183 +```
  184 +
  185 +The `tagNameProcessors` and `attrNameProcessors` options
  186 +accept an `Array` of functions with the following signature:
  187 +
  188 +```javascript
  189 +function (name){
  190 + //do something with `name`
  191 + return name
  192 +}
  193 +```
  194 +
  195 +The `attrValueProcessors` and `valueProcessors` options
  196 +accept an `Array` of functions with the following signature:
  197 +
  198 +```javascript
  199 +function (value, name) {
  200 + //`name` will be the node name or attribute name
  201 + //do something with `value`, (optionally) dependent on the node/attr name
  202 + return value
  203 +}
  204 +```
  205 +
  206 +Some processors are provided out-of-the-box and can be found in `lib/processors.js`:
  207 +
  208 +- `normalize`: transforms the name to lowercase.
  209 +(Automatically used when `options.normalize` is set to `true`)
  210 +
  211 +- `firstCharLowerCase`: transforms the first character to lower case.
  212 +E.g. 'MyTagName' becomes 'myTagName'
  213 +
  214 +- `stripPrefix`: strips the xml namespace prefix. E.g `<foo:Bar/>` will become 'Bar'.
  215 +(N.B.: the `xmlns` prefix is NOT stripped.)
  216 +
  217 +- `parseNumbers`: parses integer-like strings as integers and float-like strings as floats
  218 +E.g. "0" becomes 0 and "15.56" becomes 15.56
  219 +
  220 +- `parseBooleans`: parses boolean-like strings to booleans
  221 +E.g. "true" becomes true and "False" becomes false
  222 +
  223 +Options
  224 +=======
  225 +
  226 +Apart from the default settings, there are a number of options that can be
  227 +specified for the parser. Options are specified by ``new Parser({optionName:
  228 +value})``. Possible options are:
  229 +
  230 + * `attrkey` (default: `$`): Prefix that is used to access the attributes.
  231 + Version 0.1 default was `@`.
  232 + * `charkey` (default: `_`): Prefix that is used to access the character
  233 + content. Version 0.1 default was `#`.
  234 + * `explicitCharkey` (default: `false`)
  235 + * `trim` (default: `false`): Trim the whitespace at the beginning and end of
  236 + text nodes.
  237 + * `normalizeTags` (default: `false`): Normalize all tag names to lowercase.
  238 + * `normalize` (default: `false`): Trim whitespaces inside text nodes.
  239 + * `explicitRoot` (default: `true`): Set this if you want to get the root
  240 + node in the resulting object.
  241 + * `emptyTag` (default: `''`): what will the value of empty nodes be.
  242 + * `explicitArray` (default: `true`): Always put child nodes in an array if
  243 + true; otherwise an array is created only if there is more than one.
  244 + * `ignoreAttrs` (default: `false`): Ignore all XML attributes and only create
  245 + text nodes.
  246 + * `mergeAttrs` (default: `false`): Merge attributes and child elements as
  247 + properties of the parent, instead of keying attributes off a child
  248 + attribute object. This option is ignored if `ignoreAttrs` is `false`.
  249 + * `validator` (default `null`): You can specify a callable that validates
  250 + the resulting structure somehow, however you want. See unit tests
  251 + for an example.
  252 + * `xmlns` (default `false`): Give each element a field usually called '$ns'
  253 + (the first character is the same as attrkey) that contains its local name
  254 + and namespace URI.
  255 + * `explicitChildren` (default `false`): Put child elements to separate
  256 + property. Doesn't work with `mergeAttrs = true`. If element has no children
  257 + then "children" won't be created. Added in 0.2.5.
  258 + * `childkey` (default `$$`): Prefix that is used to access child elements if
  259 + `explicitChildren` is set to `true`. Added in 0.2.5.
  260 + * `preserveChildrenOrder` (default `false`): Modifies the behavior of
  261 + `explicitChildren` so that the value of the "children" property becomes an
  262 + ordered array. When this is `true`, every node will also get a `#name` field
  263 + whose value will correspond to the XML nodeName, so that you may iterate
  264 + the "children" array and still be able to determine node names. The named
  265 + (and potentially unordered) properties are also retained in this
  266 + configuration at the same level as the ordered "children" array. Added in
  267 + 0.4.9.
  268 + * `charsAsChildren` (default `false`): Determines whether chars should be
  269 + considered children if `explicitChildren` is on. Added in 0.2.5.
  270 + * `includeWhiteChars` (default `false`): Determines whether whitespace-only
  271 + text nodes should be included. Added in 0.4.17.
  272 + * `async` (default `false`): Should the callbacks be async? This *might* be
  273 + an incompatible change if your code depends on sync execution of callbacks.
  274 + Future versions of `xml2js` might change this default, so the recommendation
  275 + is to not depend on sync execution anyway. Added in 0.2.6.
  276 + * `strict` (default `true`): Set sax-js to strict or non-strict parsing mode.
  277 + Defaults to `true` which is *highly* recommended, since parsing HTML which
  278 + is not well-formed XML might yield just about anything. Added in 0.2.7.
  279 + * `attrNameProcessors` (default: `null`): Allows the addition of attribute
  280 + name processing functions. Accepts an `Array` of functions with following
  281 + signature:
  282 + ```javascript
  283 + function (name){
  284 + //do something with `name`
  285 + return name
  286 + }
  287 + ```
  288 + Added in 0.4.14
  289 + * `attrValueProcessors` (default: `null`): Allows the addition of attribute
  290 + value processing functions. Accepts an `Array` of functions with following
  291 + signature:
  292 + ```javascript
  293 + function (name){
  294 + //do something with `name`
  295 + return name
  296 + }
  297 + ```
  298 + Added in 0.4.1
  299 + * `tagNameProcessors` (default: `null`): Allows the addition of tag name
  300 + processing functions. Accepts an `Array` of functions with following
  301 + signature:
  302 + ```javascript
  303 + function (name){
  304 + //do something with `name`
  305 + return name
  306 + }
  307 + ```
  308 + Added in 0.4.1
  309 + * `valueProcessors` (default: `null`): Allows the addition of element value
  310 + processing functions. Accepts an `Array` of functions with following
  311 + signature:
  312 + ```javascript
  313 + function (name){
  314 + //do something with `name`
  315 + return name
  316 + }
  317 + ```
  318 + Added in 0.4.6
  319 +
  320 +Options for the `Builder` class
  321 +-------------------------------
  322 +These options are specified by ``new Builder({optionName: value})``.
  323 +Possible options are:
  324 +
  325 + * `rootName` (default `root` or the root key name): root element name to be used in case
  326 + `explicitRoot` is `false` or to override the root element name.
  327 + * `renderOpts` (default `{ 'pretty': true, 'indent': ' ', 'newline': '\n' }`):
  328 + Rendering options for xmlbuilder-js.
  329 + * pretty: prettify generated XML
  330 + * indent: whitespace for indentation (only when pretty)
  331 + * newline: newline char (only when pretty)
  332 + * `xmldec` (default `{ 'version': '1.0', 'encoding': 'UTF-8', 'standalone': true }`:
  333 + XML declaration attributes.
  334 + * `xmldec.version` A version number string, e.g. 1.0
  335 + * `xmldec.encoding` Encoding declaration, e.g. UTF-8
  336 + * `xmldec.standalone` standalone document declaration: true or false
  337 + * `doctype` (default `null`): optional DTD. Eg. `{'ext': 'hello.dtd'}`
  338 + * `headless` (default: `false`): omit the XML header. Added in 0.4.3.
  339 + * `allowSurrogateChars` (default: `false`): allows using characters from the Unicode
  340 + surrogate blocks.
  341 + * `cdata` (default: `false`): wrap text nodes in `<![CDATA[ ... ]]>` instead of
  342 + escaping when necessary. Does not add `<![CDATA[ ... ]]>` if it is not required.
  343 + Added in 0.4.5.
  344 +
  345 +`renderOpts`, `xmldec`,`doctype` and `headless` pass through to
  346 +[xmlbuilder-js](https://github.com/oozcitak/xmlbuilder-js).
  347 +
  348 +Updating to new version
  349 +=======================
  350 +
  351 +Version 0.2 changed the default parsing settings, but version 0.1.14 introduced
  352 +the default settings for version 0.2, so these settings can be tried before the
  353 +migration.
  354 +
  355 +```javascript
  356 +var xml2js = require('xml2js');
  357 +var parser = new xml2js.Parser(xml2js.defaults["0.2"]);
  358 +```
  359 +
  360 +To get the 0.1 defaults in version 0.2 you can just use
  361 +`xml2js.defaults["0.1"]` in the same place. This provides you with enough time
  362 +to migrate to the saner way of parsing in `xml2js` 0.2. We try to make the
  363 +migration as simple and gentle as possible, but some breakage cannot be
  364 +avoided.
  365 +
  366 +So, what exactly did change and why? In 0.2 we changed some defaults to parse
  367 +the XML in a more universal and sane way. So we disabled `normalize` and `trim`
  368 +so `xml2js` does not cut out any text content. You can reenable this at will of
  369 +course. A more important change is that we return the root tag in the resulting
  370 +JavaScript structure via the `explicitRoot` setting, so you need to access the
  371 +first element. This is useful for anybody who wants to know what the root node
  372 +is and preserves more information. The last major change was to enable
  373 +`explicitArray`, so everytime it is possible that one might embed more than one
  374 +sub-tag into a tag, xml2js >= 0.2 returns an array even if the array just
  375 +includes one element. This is useful when dealing with APIs that return
  376 +variable amounts of subtags.
  377 +
  378 +Running tests, development
  379 +==========================
  380 +
  381 +[![Build Status](https://travis-ci.org/Leonidas-from-XIV/node-xml2js.svg?branch=master)](https://travis-ci.org/Leonidas-from-XIV/node-xml2js)
  382 +[![Coverage Status](https://coveralls.io/repos/Leonidas-from-XIV/node-xml2js/badge.svg?branch=)](https://coveralls.io/r/Leonidas-from-XIV/node-xml2js?branch=master)
  383 +[![Dependency Status](https://david-dm.org/Leonidas-from-XIV/node-xml2js.svg)](https://david-dm.org/Leonidas-from-XIV/node-xml2js)
  384 +
  385 +The development requirements are handled by npm, you just need to install them.
  386 +We also have a number of unit tests, they can be run using `npm test` directly
  387 +from the project root. This runs zap to discover all the tests and execute
  388 +them.
  389 +
  390 +If you like to contribute, keep in mind that `xml2js` is written in
  391 +CoffeeScript, so don't develop on the JavaScript files that are checked into
  392 +the repository for convenience reasons. Also, please write some unit test to
  393 +check your behaviour and if it is some user-facing thing, add some
  394 +documentation to this README, so people will know it exists. Thanks in advance!
  395 +
  396 +Getting support
  397 +===============
  398 +
  399 +Please, if you have a problem with the library, first make sure you read this
  400 +README. If you read this far, thanks, you're good. Then, please make sure your
  401 +problem really is with `xml2js`. It is? Okay, then I'll look at it. Send me a
  402 +mail and we can talk. Please don't open issues, as I don't think that is the
  403 +proper forum for support problems. Some problems might as well really be bugs
  404 +in `xml2js`, if so I'll let you know to open an issue instead :)
  405 +
  406 +But if you know you really found a bug, feel free to open an issue instead.
  1 +// Generated by CoffeeScript 1.12.7
  2 +(function() {
  3 + "use strict";
  4 + exports.stripBOM = function(str) {
  5 + if (str[0] === '\uFEFF') {
  6 + return str.substring(1);
  7 + } else {
  8 + return str;
  9 + }
  10 + };
  11 +
  12 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.7
  2 +(function() {
  3 + "use strict";
  4 + var builder, defaults, escapeCDATA, requiresCDATA, wrapCDATA,
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + builder = require('xmlbuilder');
  8 +
  9 + defaults = require('./defaults').defaults;
  10 +
  11 + requiresCDATA = function(entry) {
  12 + return typeof entry === "string" && (entry.indexOf('&') >= 0 || entry.indexOf('>') >= 0 || entry.indexOf('<') >= 0);
  13 + };
  14 +
  15 + wrapCDATA = function(entry) {
  16 + return "<![CDATA[" + (escapeCDATA(entry)) + "]]>";
  17 + };
  18 +
  19 + escapeCDATA = function(entry) {
  20 + return entry.replace(']]>', ']]]]><![CDATA[>');
  21 + };
  22 +
  23 + exports.Builder = (function() {
  24 + function Builder(opts) {
  25 + var key, ref, value;
  26 + this.options = {};
  27 + ref = defaults["0.2"];
  28 + for (key in ref) {
  29 + if (!hasProp.call(ref, key)) continue;
  30 + value = ref[key];
  31 + this.options[key] = value;
  32 + }
  33 + for (key in opts) {
  34 + if (!hasProp.call(opts, key)) continue;
  35 + value = opts[key];
  36 + this.options[key] = value;
  37 + }
  38 + }
  39 +
  40 + Builder.prototype.buildObject = function(rootObj) {
  41 + var attrkey, charkey, render, rootElement, rootName;
  42 + attrkey = this.options.attrkey;
  43 + charkey = this.options.charkey;
  44 + if ((Object.keys(rootObj).length === 1) && (this.options.rootName === defaults['0.2'].rootName)) {
  45 + rootName = Object.keys(rootObj)[0];
  46 + rootObj = rootObj[rootName];
  47 + } else {
  48 + rootName = this.options.rootName;
  49 + }
  50 + render = (function(_this) {
  51 + return function(element, obj) {
  52 + var attr, child, entry, index, key, value;
  53 + if (typeof obj !== 'object') {
  54 + if (_this.options.cdata && requiresCDATA(obj)) {
  55 + element.raw(wrapCDATA(obj));
  56 + } else {
  57 + element.txt(obj);
  58 + }
  59 + } else if (Array.isArray(obj)) {
  60 + for (index in obj) {
  61 + if (!hasProp.call(obj, index)) continue;
  62 + child = obj[index];
  63 + for (key in child) {
  64 + entry = child[key];
  65 + element = render(element.ele(key), entry).up();
  66 + }
  67 + }
  68 + } else {
  69 + for (key in obj) {
  70 + if (!hasProp.call(obj, key)) continue;
  71 + child = obj[key];
  72 + if (key === attrkey) {
  73 + if (typeof child === "object") {
  74 + for (attr in child) {
  75 + value = child[attr];
  76 + element = element.att(attr, value);
  77 + }
  78 + }
  79 + } else if (key === charkey) {
  80 + if (_this.options.cdata && requiresCDATA(child)) {
  81 + element = element.raw(wrapCDATA(child));
  82 + } else {
  83 + element = element.txt(child);
  84 + }
  85 + } else if (Array.isArray(child)) {
  86 + for (index in child) {
  87 + if (!hasProp.call(child, index)) continue;
  88 + entry = child[index];
  89 + if (typeof entry === 'string') {
  90 + if (_this.options.cdata && requiresCDATA(entry)) {
  91 + element = element.ele(key).raw(wrapCDATA(entry)).up();
  92 + } else {
  93 + element = element.ele(key, entry).up();
  94 + }
  95 + } else {
  96 + element = render(element.ele(key), entry).up();
  97 + }
  98 + }
  99 + } else if (typeof child === "object") {
  100 + element = render(element.ele(key), child).up();
  101 + } else {
  102 + if (typeof child === 'string' && _this.options.cdata && requiresCDATA(child)) {
  103 + element = element.ele(key).raw(wrapCDATA(child)).up();
  104 + } else {
  105 + if (child == null) {
  106 + child = '';
  107 + }
  108 + element = element.ele(key, child.toString()).up();
  109 + }
  110 + }
  111 + }
  112 + }
  113 + return element;
  114 + };
  115 + })(this);
  116 + rootElement = builder.create(rootName, this.options.xmldec, this.options.doctype, {
  117 + headless: this.options.headless,
  118 + allowSurrogateChars: this.options.allowSurrogateChars
  119 + });
  120 + return render(rootElement, rootObj).end(this.options.renderOpts);
  121 + };
  122 +
  123 + return Builder;
  124 +
  125 + })();
  126 +
  127 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.7
  2 +(function() {
  3 + exports.defaults = {
  4 + "0.1": {
  5 + explicitCharkey: false,
  6 + trim: true,
  7 + normalize: true,
  8 + normalizeTags: false,
  9 + attrkey: "@",
  10 + charkey: "#",
  11 + explicitArray: false,
  12 + ignoreAttrs: false,
  13 + mergeAttrs: false,
  14 + explicitRoot: false,
  15 + validator: null,
  16 + xmlns: false,
  17 + explicitChildren: false,
  18 + childkey: '@@',
  19 + charsAsChildren: false,
  20 + includeWhiteChars: false,
  21 + async: false,
  22 + strict: true,
  23 + attrNameProcessors: null,
  24 + attrValueProcessors: null,
  25 + tagNameProcessors: null,
  26 + valueProcessors: null,
  27 + emptyTag: ''
  28 + },
  29 + "0.2": {
  30 + explicitCharkey: false,
  31 + trim: false,
  32 + normalize: false,
  33 + normalizeTags: false,
  34 + attrkey: "$",
  35 + charkey: "_",
  36 + explicitArray: true,
  37 + ignoreAttrs: false,
  38 + mergeAttrs: false,
  39 + explicitRoot: true,
  40 + validator: null,
  41 + xmlns: false,
  42 + explicitChildren: false,
  43 + preserveChildrenOrder: false,
  44 + childkey: '$$',
  45 + charsAsChildren: false,
  46 + includeWhiteChars: false,
  47 + async: false,
  48 + strict: true,
  49 + attrNameProcessors: null,
  50 + attrValueProcessors: null,
  51 + tagNameProcessors: null,
  52 + valueProcessors: null,
  53 + rootName: 'root',
  54 + xmldec: {
  55 + 'version': '1.0',
  56 + 'encoding': 'UTF-8',
  57 + 'standalone': true
  58 + },
  59 + doctype: null,
  60 + renderOpts: {
  61 + 'pretty': true,
  62 + 'indent': ' ',
  63 + 'newline': '\n'
  64 + },
  65 + headless: false,
  66 + chunkSize: 10000,
  67 + emptyTag: '',
  68 + cdata: false
  69 + }
  70 + };
  71 +
  72 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.7
  2 +(function() {
  3 + "use strict";
  4 + var bom, defaults, events, isEmpty, processItem, processors, sax, setImmediate,
  5 + bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
  6 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  7 + hasProp = {}.hasOwnProperty;
  8 +
  9 + sax = require('sax');
  10 +
  11 + events = require('events');
  12 +
  13 + bom = require('./bom');
  14 +
  15 + processors = require('./processors');
  16 +
  17 + setImmediate = require('timers').setImmediate;
  18 +
  19 + defaults = require('./defaults').defaults;
  20 +
  21 + isEmpty = function(thing) {
  22 + return typeof thing === "object" && (thing != null) && Object.keys(thing).length === 0;
  23 + };
  24 +
  25 + processItem = function(processors, item, key) {
  26 + var i, len, process;
  27 + for (i = 0, len = processors.length; i < len; i++) {
  28 + process = processors[i];
  29 + item = process(item, key);
  30 + }
  31 + return item;
  32 + };
  33 +
  34 + exports.Parser = (function(superClass) {
  35 + extend(Parser, superClass);
  36 +
  37 + function Parser(opts) {
  38 + this.parseString = bind(this.parseString, this);
  39 + this.reset = bind(this.reset, this);
  40 + this.assignOrPush = bind(this.assignOrPush, this);
  41 + this.processAsync = bind(this.processAsync, this);
  42 + var key, ref, value;
  43 + if (!(this instanceof exports.Parser)) {
  44 + return new exports.Parser(opts);
  45 + }
  46 + this.options = {};
  47 + ref = defaults["0.2"];
  48 + for (key in ref) {
  49 + if (!hasProp.call(ref, key)) continue;
  50 + value = ref[key];
  51 + this.options[key] = value;
  52 + }
  53 + for (key in opts) {
  54 + if (!hasProp.call(opts, key)) continue;
  55 + value = opts[key];
  56 + this.options[key] = value;
  57 + }
  58 + if (this.options.xmlns) {
  59 + this.options.xmlnskey = this.options.attrkey + "ns";
  60 + }
  61 + if (this.options.normalizeTags) {
  62 + if (!this.options.tagNameProcessors) {
  63 + this.options.tagNameProcessors = [];
  64 + }
  65 + this.options.tagNameProcessors.unshift(processors.normalize);
  66 + }
  67 + this.reset();
  68 + }
  69 +
  70 + Parser.prototype.processAsync = function() {
  71 + var chunk, err;
  72 + try {
  73 + if (this.remaining.length <= this.options.chunkSize) {
  74 + chunk = this.remaining;
  75 + this.remaining = '';
  76 + this.saxParser = this.saxParser.write(chunk);
  77 + return this.saxParser.close();
  78 + } else {
  79 + chunk = this.remaining.substr(0, this.options.chunkSize);
  80 + this.remaining = this.remaining.substr(this.options.chunkSize, this.remaining.length);
  81 + this.saxParser = this.saxParser.write(chunk);
  82 + return setImmediate(this.processAsync);
  83 + }
  84 + } catch (error1) {
  85 + err = error1;
  86 + if (!this.saxParser.errThrown) {
  87 + this.saxParser.errThrown = true;
  88 + return this.emit(err);
  89 + }
  90 + }
  91 + };
  92 +
  93 + Parser.prototype.assignOrPush = function(obj, key, newValue) {
  94 + if (!(key in obj)) {
  95 + if (!this.options.explicitArray) {
  96 + return obj[key] = newValue;
  97 + } else {
  98 + return obj[key] = [newValue];
  99 + }
  100 + } else {
  101 + if (!(obj[key] instanceof Array)) {
  102 + obj[key] = [obj[key]];
  103 + }
  104 + return obj[key].push(newValue);
  105 + }
  106 + };
  107 +
  108 + Parser.prototype.reset = function() {
  109 + var attrkey, charkey, ontext, stack;
  110 + this.removeAllListeners();
  111 + this.saxParser = sax.parser(this.options.strict, {
  112 + trim: false,
  113 + normalize: false,
  114 + xmlns: this.options.xmlns
  115 + });
  116 + this.saxParser.errThrown = false;
  117 + this.saxParser.onerror = (function(_this) {
  118 + return function(error) {
  119 + _this.saxParser.resume();
  120 + if (!_this.saxParser.errThrown) {
  121 + _this.saxParser.errThrown = true;
  122 + return _this.emit("error", error);
  123 + }
  124 + };
  125 + })(this);
  126 + this.saxParser.onend = (function(_this) {
  127 + return function() {
  128 + if (!_this.saxParser.ended) {
  129 + _this.saxParser.ended = true;
  130 + return _this.emit("end", _this.resultObject);
  131 + }
  132 + };
  133 + })(this);
  134 + this.saxParser.ended = false;
  135 + this.EXPLICIT_CHARKEY = this.options.explicitCharkey;
  136 + this.resultObject = null;
  137 + stack = [];
  138 + attrkey = this.options.attrkey;
  139 + charkey = this.options.charkey;
  140 + this.saxParser.onopentag = (function(_this) {
  141 + return function(node) {
  142 + var key, newValue, obj, processedKey, ref;
  143 + obj = {};
  144 + obj[charkey] = "";
  145 + if (!_this.options.ignoreAttrs) {
  146 + ref = node.attributes;
  147 + for (key in ref) {
  148 + if (!hasProp.call(ref, key)) continue;
  149 + if (!(attrkey in obj) && !_this.options.mergeAttrs) {
  150 + obj[attrkey] = {};
  151 + }
  152 + newValue = _this.options.attrValueProcessors ? processItem(_this.options.attrValueProcessors, node.attributes[key], key) : node.attributes[key];
  153 + processedKey = _this.options.attrNameProcessors ? processItem(_this.options.attrNameProcessors, key) : key;
  154 + if (_this.options.mergeAttrs) {
  155 + _this.assignOrPush(obj, processedKey, newValue);
  156 + } else {
  157 + obj[attrkey][processedKey] = newValue;
  158 + }
  159 + }
  160 + }
  161 + obj["#name"] = _this.options.tagNameProcessors ? processItem(_this.options.tagNameProcessors, node.name) : node.name;
  162 + if (_this.options.xmlns) {
  163 + obj[_this.options.xmlnskey] = {
  164 + uri: node.uri,
  165 + local: node.local
  166 + };
  167 + }
  168 + return stack.push(obj);
  169 + };
  170 + })(this);
  171 + this.saxParser.onclosetag = (function(_this) {
  172 + return function() {
  173 + var cdata, emptyStr, key, node, nodeName, obj, objClone, old, s, xpath;
  174 + obj = stack.pop();
  175 + nodeName = obj["#name"];
  176 + if (!_this.options.explicitChildren || !_this.options.preserveChildrenOrder) {
  177 + delete obj["#name"];
  178 + }
  179 + if (obj.cdata === true) {
  180 + cdata = obj.cdata;
  181 + delete obj.cdata;
  182 + }
  183 + s = stack[stack.length - 1];
  184 + if (obj[charkey].match(/^\s*$/) && !cdata) {
  185 + emptyStr = obj[charkey];
  186 + delete obj[charkey];
  187 + } else {
  188 + if (_this.options.trim) {
  189 + obj[charkey] = obj[charkey].trim();
  190 + }
  191 + if (_this.options.normalize) {
  192 + obj[charkey] = obj[charkey].replace(/\s{2,}/g, " ").trim();
  193 + }
  194 + obj[charkey] = _this.options.valueProcessors ? processItem(_this.options.valueProcessors, obj[charkey], nodeName) : obj[charkey];
  195 + if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) {
  196 + obj = obj[charkey];
  197 + }
  198 + }
  199 + if (isEmpty(obj)) {
  200 + obj = _this.options.emptyTag !== '' ? _this.options.emptyTag : emptyStr;
  201 + }
  202 + if (_this.options.validator != null) {
  203 + xpath = "/" + ((function() {
  204 + var i, len, results;
  205 + results = [];
  206 + for (i = 0, len = stack.length; i < len; i++) {
  207 + node = stack[i];
  208 + results.push(node["#name"]);
  209 + }
  210 + return results;
  211 + })()).concat(nodeName).join("/");
  212 + (function() {
  213 + var err;
  214 + try {
  215 + return obj = _this.options.validator(xpath, s && s[nodeName], obj);
  216 + } catch (error1) {
  217 + err = error1;
  218 + return _this.emit("error", err);
  219 + }
  220 + })();
  221 + }
  222 + if (_this.options.explicitChildren && !_this.options.mergeAttrs && typeof obj === 'object') {
  223 + if (!_this.options.preserveChildrenOrder) {
  224 + node = {};
  225 + if (_this.options.attrkey in obj) {
  226 + node[_this.options.attrkey] = obj[_this.options.attrkey];
  227 + delete obj[_this.options.attrkey];
  228 + }
  229 + if (!_this.options.charsAsChildren && _this.options.charkey in obj) {
  230 + node[_this.options.charkey] = obj[_this.options.charkey];
  231 + delete obj[_this.options.charkey];
  232 + }
  233 + if (Object.getOwnPropertyNames(obj).length > 0) {
  234 + node[_this.options.childkey] = obj;
  235 + }
  236 + obj = node;
  237 + } else if (s) {
  238 + s[_this.options.childkey] = s[_this.options.childkey] || [];
  239 + objClone = {};
  240 + for (key in obj) {
  241 + if (!hasProp.call(obj, key)) continue;
  242 + objClone[key] = obj[key];
  243 + }
  244 + s[_this.options.childkey].push(objClone);
  245 + delete obj["#name"];
  246 + if (Object.keys(obj).length === 1 && charkey in obj && !_this.EXPLICIT_CHARKEY) {
  247 + obj = obj[charkey];
  248 + }
  249 + }
  250 + }
  251 + if (stack.length > 0) {
  252 + return _this.assignOrPush(s, nodeName, obj);
  253 + } else {
  254 + if (_this.options.explicitRoot) {
  255 + old = obj;
  256 + obj = {};
  257 + obj[nodeName] = old;
  258 + }
  259 + _this.resultObject = obj;
  260 + _this.saxParser.ended = true;
  261 + return _this.emit("end", _this.resultObject);
  262 + }
  263 + };
  264 + })(this);
  265 + ontext = (function(_this) {
  266 + return function(text) {
  267 + var charChild, s;
  268 + s = stack[stack.length - 1];
  269 + if (s) {
  270 + s[charkey] += text;
  271 + if (_this.options.explicitChildren && _this.options.preserveChildrenOrder && _this.options.charsAsChildren && (_this.options.includeWhiteChars || text.replace(/\\n/g, '').trim() !== '')) {
  272 + s[_this.options.childkey] = s[_this.options.childkey] || [];
  273 + charChild = {
  274 + '#name': '__text__'
  275 + };
  276 + charChild[charkey] = text;
  277 + if (_this.options.normalize) {
  278 + charChild[charkey] = charChild[charkey].replace(/\s{2,}/g, " ").trim();
  279 + }
  280 + s[_this.options.childkey].push(charChild);
  281 + }
  282 + return s;
  283 + }
  284 + };
  285 + })(this);
  286 + this.saxParser.ontext = ontext;
  287 + return this.saxParser.oncdata = (function(_this) {
  288 + return function(text) {
  289 + var s;
  290 + s = ontext(text);
  291 + if (s) {
  292 + return s.cdata = true;
  293 + }
  294 + };
  295 + })(this);
  296 + };
  297 +
  298 + Parser.prototype.parseString = function(str, cb) {
  299 + var err;
  300 + if ((cb != null) && typeof cb === "function") {
  301 + this.on("end", function(result) {
  302 + this.reset();
  303 + return cb(null, result);
  304 + });
  305 + this.on("error", function(err) {
  306 + this.reset();
  307 + return cb(err);
  308 + });
  309 + }
  310 + try {
  311 + str = str.toString();
  312 + if (str.trim() === '') {
  313 + this.emit("end", null);
  314 + return true;
  315 + }
  316 + str = bom.stripBOM(str);
  317 + if (this.options.async) {
  318 + this.remaining = str;
  319 + setImmediate(this.processAsync);
  320 + return this.saxParser;
  321 + }
  322 + return this.saxParser.write(str).close();
  323 + } catch (error1) {
  324 + err = error1;
  325 + if (!(this.saxParser.errThrown || this.saxParser.ended)) {
  326 + this.emit('error', err);
  327 + return this.saxParser.errThrown = true;
  328 + } else if (this.saxParser.ended) {
  329 + throw err;
  330 + }
  331 + }
  332 + };
  333 +
  334 + return Parser;
  335 +
  336 + })(events.EventEmitter);
  337 +
  338 + exports.parseString = function(str, a, b) {
  339 + var cb, options, parser;
  340 + if (b != null) {
  341 + if (typeof b === 'function') {
  342 + cb = b;
  343 + }
  344 + if (typeof a === 'object') {
  345 + options = a;
  346 + }
  347 + } else {
  348 + if (typeof a === 'function') {
  349 + cb = a;
  350 + }
  351 + options = {};
  352 + }
  353 + parser = new exports.Parser(options);
  354 + return parser.parseString(str, cb);
  355 + };
  356 +
  357 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.7
  2 +(function() {
  3 + "use strict";
  4 + var prefixMatch;
  5 +
  6 + prefixMatch = new RegExp(/(?!xmlns)^.*:/);
  7 +
  8 + exports.normalize = function(str) {
  9 + return str.toLowerCase();
  10 + };
  11 +
  12 + exports.firstCharLowerCase = function(str) {
  13 + return str.charAt(0).toLowerCase() + str.slice(1);
  14 + };
  15 +
  16 + exports.stripPrefix = function(str) {
  17 + return str.replace(prefixMatch, '');
  18 + };
  19 +
  20 + exports.parseNumbers = function(str) {
  21 + if (!isNaN(str)) {
  22 + str = str % 1 === 0 ? parseInt(str, 10) : parseFloat(str);
  23 + }
  24 + return str;
  25 + };
  26 +
  27 + exports.parseBooleans = function(str) {
  28 + if (/^(?:true|false)$/i.test(str)) {
  29 + str = str.toLowerCase() === 'true';
  30 + }
  31 + return str;
  32 + };
  33 +
  34 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.7
  2 +(function() {
  3 + "use strict";
  4 + var builder, defaults, parser, processors,
  5 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  6 + hasProp = {}.hasOwnProperty;
  7 +
  8 + defaults = require('./defaults');
  9 +
  10 + builder = require('./builder');
  11 +
  12 + parser = require('./parser');
  13 +
  14 + processors = require('./processors');
  15 +
  16 + exports.defaults = defaults.defaults;
  17 +
  18 + exports.processors = processors;
  19 +
  20 + exports.ValidationError = (function(superClass) {
  21 + extend(ValidationError, superClass);
  22 +
  23 + function ValidationError(message) {
  24 + this.message = message;
  25 + }
  26 +
  27 + return ValidationError;
  28 +
  29 + })(Error);
  30 +
  31 + exports.Builder = builder.Builder;
  32 +
  33 + exports.Parser = parser.Parser;
  34 +
  35 + exports.parseString = parser.parseString;
  36 +
  37 +}).call(this);
  1 +{
  2 + "_args": [
  3 + [
  4 + {
  5 + "raw": "xml2js",
  6 + "scope": null,
  7 + "escapedName": "xml2js",
  8 + "name": "xml2js",
  9 + "rawSpec": "",
  10 + "spec": "latest",
  11 + "type": "tag"
  12 + },
  13 + "/Users/fzy/project/koa2_Sequelize_project"
  14 + ]
  15 + ],
  16 + "_from": "xml2js@latest",
  17 + "_id": "xml2js@0.4.19",
  18 + "_inCache": true,
  19 + "_location": "/xml2js",
  20 + "_nodeVersion": "8.4.0",
  21 + "_npmOperationalInternal": {
  22 + "host": "s3://npm-registry-packages",
  23 + "tmp": "tmp/xml2js-0.4.19.tgz_1503387862909_0.5125016651581973"
  24 + },
  25 + "_npmUser": {
  26 + "name": "leonidas",
  27 + "email": "marek@xivilization.net"
  28 + },
  29 + "_npmVersion": "5.3.0",
  30 + "_phantomChildren": {},
  31 + "_requested": {
  32 + "raw": "xml2js",
  33 + "scope": null,
  34 + "escapedName": "xml2js",
  35 + "name": "xml2js",
  36 + "rawSpec": "",
  37 + "spec": "latest",
  38 + "type": "tag"
  39 + },
  40 + "_requiredBy": [
  41 + "#USER"
  42 + ],
  43 + "_resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
  44 + "_shasum": "686c20f213209e94abf0d1bcf1efaa291c7827a7",
  45 + "_shrinkwrap": null,
  46 + "_spec": "xml2js",
  47 + "_where": "/Users/fzy/project/koa2_Sequelize_project",
  48 + "author": {
  49 + "name": "Marek Kubica",
  50 + "email": "marek@xivilization.net",
  51 + "url": "https://xivilization.net"
  52 + },
  53 + "bugs": {
  54 + "url": "https://github.com/Leonidas-from-XIV/node-xml2js/issues"
  55 + },
  56 + "contributors": [
  57 + {
  58 + "name": "maqr",
  59 + "email": "maqr.lollerskates@gmail.com",
  60 + "url": "https://github.com/maqr"
  61 + },
  62 + {
  63 + "name": "Ben Weaver",
  64 + "url": "http://benweaver.com/"
  65 + },
  66 + {
  67 + "name": "Jae Kwon",
  68 + "url": "https://github.com/jaekwon"
  69 + },
  70 + {
  71 + "name": "Jim Robert"
  72 + },
  73 + {
  74 + "name": "Ștefan Rusu",
  75 + "url": "http://www.saltwaterc.eu/"
  76 + },
  77 + {
  78 + "name": "Carter Cole",
  79 + "email": "carter.cole@cartercole.com",
  80 + "url": "http://cartercole.com/"
  81 + },
  82 + {
  83 + "name": "Kurt Raschke",
  84 + "email": "kurt@kurtraschke.com",
  85 + "url": "http://www.kurtraschke.com/"
  86 + },
  87 + {
  88 + "name": "Contra",
  89 + "email": "contra@australia.edu",
  90 + "url": "https://github.com/Contra"
  91 + },
  92 + {
  93 + "name": "Marcelo Diniz",
  94 + "email": "marudiniz@gmail.com",
  95 + "url": "https://github.com/mdiniz"
  96 + },
  97 + {
  98 + "name": "Michael Hart",
  99 + "url": "https://github.com/mhart"
  100 + },
  101 + {
  102 + "name": "Zachary Scott",
  103 + "email": "zachary@zacharyscott.net",
  104 + "url": "http://zacharyscott.net/"
  105 + },
  106 + {
  107 + "name": "Raoul Millais",
  108 + "url": "https://github.com/raoulmillais"
  109 + },
  110 + {
  111 + "name": "Salsita Software",
  112 + "url": "http://www.salsitasoft.com/"
  113 + },
  114 + {
  115 + "name": "Mike Schilling",
  116 + "email": "mike@emotive.com",
  117 + "url": "http://www.emotive.com/"
  118 + },
  119 + {
  120 + "name": "Jackson Tian",
  121 + "email": "shyvo1987@gmail.com",
  122 + "url": "http://weibo.com/shyvo"
  123 + },
  124 + {
  125 + "name": "Mikhail Zyatin",
  126 + "email": "mikhail.zyatin@gmail.com",
  127 + "url": "https://github.com/Sitin"
  128 + },
  129 + {
  130 + "name": "Chris Tavares",
  131 + "email": "ctavares@microsoft.com",
  132 + "url": "https://github.com/christav"
  133 + },
  134 + {
  135 + "name": "Frank Xu",
  136 + "email": "yyfrankyy@gmail.com",
  137 + "url": "http://f2e.us/"
  138 + },
  139 + {
  140 + "name": "Guido D'Albore",
  141 + "email": "guido@bitstorm.it",
  142 + "url": "http://www.bitstorm.it/"
  143 + },
  144 + {
  145 + "name": "Jack Senechal",
  146 + "url": "http://jacksenechal.com/"
  147 + },
  148 + {
  149 + "name": "Matthias Hölzl",
  150 + "email": "tc@xantira.com",
  151 + "url": "https://github.com/hoelzl"
  152 + },
  153 + {
  154 + "name": "Camille Reynders",
  155 + "email": "info@creynders.be",
  156 + "url": "http://www.creynders.be/"
  157 + },
  158 + {
  159 + "name": "Taylor Gautier",
  160 + "url": "https://github.com/tsgautier"
  161 + },
  162 + {
  163 + "name": "Todd Bryan",
  164 + "url": "https://github.com/toddrbryan"
  165 + },
  166 + {
  167 + "name": "Leore Avidar",
  168 + "email": "leore.avidar@gmail.com",
  169 + "url": "http://leoreavidar.com/"
  170 + },
  171 + {
  172 + "name": "Dave Aitken",
  173 + "email": "dave.aitken@gmail.com",
  174 + "url": "http://www.actionshrimp.com/"
  175 + },
  176 + {
  177 + "name": "Shaney Orrowe",
  178 + "email": "shaney.orrowe@practiceweb.co.uk"
  179 + },
  180 + {
  181 + "name": "Candle",
  182 + "email": "candle@candle.me.uk"
  183 + },
  184 + {
  185 + "name": "Jess Telford",
  186 + "email": "hi@jes.st",
  187 + "url": "http://jes.st"
  188 + },
  189 + {
  190 + "name": "Tom Hughes",
  191 + "email": "<tom@compton.nu",
  192 + "url": "http://compton.nu/"
  193 + },
  194 + {
  195 + "name": "Piotr Rochala",
  196 + "url": "http://rocha.la/"
  197 + },
  198 + {
  199 + "name": "Michael Avila",
  200 + "url": "https://github.com/michaelavila"
  201 + },
  202 + {
  203 + "name": "Ryan Gahl",
  204 + "url": "https://github.com/ryedin"
  205 + },
  206 + {
  207 + "name": "Eric Laberge",
  208 + "email": "e.laberge@gmail.com",
  209 + "url": "https://github.com/elaberge"
  210 + },
  211 + {
  212 + "name": "Benjamin E. Coe",
  213 + "email": "ben@npmjs.com",
  214 + "url": "https://twitter.com/benjamincoe"
  215 + },
  216 + {
  217 + "name": "Stephen Cresswell",
  218 + "url": "https://github.com/cressie176"
  219 + },
  220 + {
  221 + "name": "Pascal Ehlert",
  222 + "email": "pascal@hacksrus.net",
  223 + "url": "http://www.hacksrus.net/"
  224 + },
  225 + {
  226 + "name": "Tom Spencer",
  227 + "email": "fiznool@gmail.com",
  228 + "url": "http://fiznool.com/"
  229 + },
  230 + {
  231 + "name": "Tristian Flanagan",
  232 + "email": "tflanagan@datacollaborative.com",
  233 + "url": "https://github.com/tflanagan"
  234 + },
  235 + {
  236 + "name": "Tim Johns",
  237 + "email": "timjohns@yahoo.com",
  238 + "url": "https://github.com/TimJohns"
  239 + },
  240 + {
  241 + "name": "Bogdan Chadkin",
  242 + "email": "trysound@yandex.ru",
  243 + "url": "https://github.com/TrySound"
  244 + },
  245 + {
  246 + "name": "David Wood",
  247 + "email": "david.p.wood@gmail.com",
  248 + "url": "http://codesleuth.co.uk/"
  249 + },
  250 + {
  251 + "name": "Nicolas Maquet",
  252 + "url": "https://github.com/nmaquet"
  253 + },
  254 + {
  255 + "name": "Lovell Fuller",
  256 + "url": "http://lovell.info/"
  257 + },
  258 + {
  259 + "name": "d3adc0d3",
  260 + "url": "https://github.com/d3adc0d3"
  261 + }
  262 + ],
  263 + "dependencies": {
  264 + "sax": ">=0.6.0",
  265 + "xmlbuilder": "~9.0.1"
  266 + },
  267 + "description": "Simple XML to JavaScript object converter.",
  268 + "devDependencies": {
  269 + "coffee-script": ">=1.10.0",
  270 + "coveralls": "^2.11.2",
  271 + "diff": ">=1.0.8",
  272 + "docco": ">=0.6.2",
  273 + "nyc": ">=2.2.1",
  274 + "zap": ">=0.2.9"
  275 + },
  276 + "directories": {
  277 + "lib": "./lib"
  278 + },
  279 + "dist": {
  280 + "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
  281 + "shasum": "686c20f213209e94abf0d1bcf1efaa291c7827a7",
  282 + "tarball": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz"
  283 + },
  284 + "files": [
  285 + "lib"
  286 + ],
  287 + "gitHead": "1ab44ea837eff59305bd11f0e1a1e542e7c3e79f",
  288 + "homepage": "https://github.com/Leonidas-from-XIV/node-xml2js",
  289 + "keywords": [
  290 + "xml",
  291 + "json"
  292 + ],
  293 + "license": "MIT",
  294 + "main": "./lib/xml2js",
  295 + "maintainers": [
  296 + {
  297 + "name": "leonidas",
  298 + "email": "marek@xivilization.net"
  299 + }
  300 + ],
  301 + "name": "xml2js",
  302 + "optionalDependencies": {},
  303 + "readme": "node-xml2js\n===========\n\nEver had the urge to parse XML? And wanted to access the data in some sane,\neasy way? Don't want to compile a C parser, for whatever reason? Then xml2js is\nwhat you're looking for!\n\nDescription\n===========\n\nSimple XML to JavaScript object converter. It supports bi-directional conversion.\nUses [sax-js](https://github.com/isaacs/sax-js/) and\n[xmlbuilder-js](https://github.com/oozcitak/xmlbuilder-js/).\n\nNote: If you're looking for a full DOM parser, you probably want\n[JSDom](https://github.com/tmpvar/jsdom).\n\nInstallation\n============\n\nSimplest way to install `xml2js` is to use [npm](http://npmjs.org), just `npm\ninstall xml2js` which will download xml2js and all dependencies.\n\nxml2js is also available via [Bower](http://bower.io/), just `bower install\nxml2js` which will download xml2js and all dependencies.\n\nUsage\n=====\n\nNo extensive tutorials required because you are a smart developer! The task of\nparsing XML should be an easy one, so let's make it so! Here's some examples.\n\nShoot-and-forget usage\n----------------------\n\nYou want to parse XML as simple and easy as possible? It's dangerous to go\nalone, take this:\n\n```javascript\nvar parseString = require('xml2js').parseString;\nvar xml = \"<root>Hello xml2js!</root>\"\nparseString(xml, function (err, result) {\n console.dir(result);\n});\n```\n\nCan't get easier than this, right? This works starting with `xml2js` 0.2.3.\nWith CoffeeScript it looks like this:\n\n```coffeescript\n{parseString} = require 'xml2js'\nxml = \"<root>Hello xml2js!</root>\"\nparseString xml, (err, result) ->\n console.dir result\n```\n\nIf you need some special options, fear not, `xml2js` supports a number of\noptions (see below), you can specify these as second argument:\n\n```javascript\nparseString(xml, {trim: true}, function (err, result) {\n});\n```\n\nSimple as pie usage\n-------------------\n\nThat's right, if you have been using xml-simple or a home-grown\nwrapper, this was added in 0.1.11 just for you:\n\n```javascript\nvar fs = require('fs'),\n xml2js = require('xml2js');\n\nvar parser = new xml2js.Parser();\nfs.readFile(__dirname + '/foo.xml', function(err, data) {\n parser.parseString(data, function (err, result) {\n console.dir(result);\n console.log('Done');\n });\n});\n```\n\nLook ma, no event listeners!\n\nYou can also use `xml2js` from\n[CoffeeScript](https://github.com/jashkenas/coffeescript), further reducing\nthe clutter:\n\n```coffeescript\nfs = require 'fs',\nxml2js = require 'xml2js'\n\nparser = new xml2js.Parser()\nfs.readFile __dirname + '/foo.xml', (err, data) ->\n parser.parseString data, (err, result) ->\n console.dir result\n console.log 'Done.'\n```\n\nBut what happens if you forget the `new` keyword to create a new `Parser`? In\nthe middle of a nightly coding session, it might get lost, after all. Worry\nnot, we got you covered! Starting with 0.2.8 you can also leave it out, in\nwhich case `xml2js` will helpfully add it for you, no bad surprises and\ninexplicable bugs!\n\nParsing multiple files\n----------------------\n\nIf you want to parse multiple files, you have multiple possibilities:\n\n * You can create one `xml2js.Parser` per file. That's the recommended one\n and is promised to always *just work*.\n * You can call `reset()` on your parser object.\n * You can hope everything goes well anyway. This behaviour is not\n guaranteed work always, if ever. Use option #1 if possible. Thanks!\n\nSo you wanna some JSON?\n-----------------------\n\nJust wrap the `result` object in a call to `JSON.stringify` like this\n`JSON.stringify(result)`. You get a string containing the JSON representation\nof the parsed object that you can feed to JSON-hungry consumers.\n\nDisplaying results\n------------------\n\nYou might wonder why, using `console.dir` or `console.log` the output at some\nlevel is only `[Object]`. Don't worry, this is not because `xml2js` got lazy.\nThat's because Node uses `util.inspect` to convert the object into strings and\nthat function stops after `depth=2` which is a bit low for most XML.\n\nTo display the whole deal, you can use `console.log(util.inspect(result, false,\nnull))`, which displays the whole result.\n\nSo much for that, but what if you use\n[eyes](https://github.com/cloudhead/eyes.js) for nice colored output and it\ntruncates the output with `…`? Don't fear, there's also a solution for that,\nyou just need to increase the `maxLength` limit by creating a custom inspector\n`var inspect = require('eyes').inspector({maxLength: false})` and then you can\neasily `inspect(result)`.\n\nXML builder usage\n-----------------\n\nSince 0.4.0, objects can be also be used to build XML:\n\n```javascript\nvar fs = require('fs'),\n xml2js = require('xml2js');\n\nvar obj = {name: \"Super\", Surname: \"Man\", age: 23};\n\nvar builder = new xml2js.Builder();\nvar xml = builder.buildObject(obj);\n```\n\nAt the moment, a one to one bi-directional conversion is guaranteed only for\ndefault configuration, except for `attrkey`, `charkey` and `explicitArray` options\nyou can redefine to your taste. Writing CDATA is supported via setting the `cdata`\noption to `true`.\n\nProcessing attribute, tag names and values\n------------------------------------------\n\nSince 0.4.1 you can optionally provide the parser with attribute name and tag name processors as well as element value processors (Since 0.4.14, you can also optionally provide the parser with attribute value processors):\n\n```javascript\n\nfunction nameToUpperCase(name){\n return name.toUpperCase();\n}\n\n//transform all attribute and tag names and values to uppercase\nparseString(xml, {\n tagNameProcessors: [nameToUpperCase],\n attrNameProcessors: [nameToUpperCase],\n valueProcessors: [nameToUpperCase],\n attrValueProcessors: [nameToUpperCase]},\n function (err, result) {\n // processed data\n});\n```\n\nThe `tagNameProcessors` and `attrNameProcessors` options\naccept an `Array` of functions with the following signature:\n\n```javascript\nfunction (name){\n //do something with `name`\n return name\n}\n```\n\nThe `attrValueProcessors` and `valueProcessors` options\naccept an `Array` of functions with the following signature:\n\n```javascript\nfunction (value, name) {\n //`name` will be the node name or attribute name\n //do something with `value`, (optionally) dependent on the node/attr name\n return value\n}\n```\n\nSome processors are provided out-of-the-box and can be found in `lib/processors.js`:\n\n- `normalize`: transforms the name to lowercase.\n(Automatically used when `options.normalize` is set to `true`)\n\n- `firstCharLowerCase`: transforms the first character to lower case.\nE.g. 'MyTagName' becomes 'myTagName'\n\n- `stripPrefix`: strips the xml namespace prefix. E.g `<foo:Bar/>` will become 'Bar'.\n(N.B.: the `xmlns` prefix is NOT stripped.)\n\n- `parseNumbers`: parses integer-like strings as integers and float-like strings as floats\nE.g. \"0\" becomes 0 and \"15.56\" becomes 15.56\n\n- `parseBooleans`: parses boolean-like strings to booleans\nE.g. \"true\" becomes true and \"False\" becomes false\n\nOptions\n=======\n\nApart from the default settings, there are a number of options that can be\nspecified for the parser. Options are specified by ``new Parser({optionName:\nvalue})``. Possible options are:\n\n * `attrkey` (default: `$`): Prefix that is used to access the attributes.\n Version 0.1 default was `@`.\n * `charkey` (default: `_`): Prefix that is used to access the character\n content. Version 0.1 default was `#`.\n * `explicitCharkey` (default: `false`)\n * `trim` (default: `false`): Trim the whitespace at the beginning and end of\n text nodes.\n * `normalizeTags` (default: `false`): Normalize all tag names to lowercase.\n * `normalize` (default: `false`): Trim whitespaces inside text nodes.\n * `explicitRoot` (default: `true`): Set this if you want to get the root\n node in the resulting object.\n * `emptyTag` (default: `''`): what will the value of empty nodes be.\n * `explicitArray` (default: `true`): Always put child nodes in an array if\n true; otherwise an array is created only if there is more than one.\n * `ignoreAttrs` (default: `false`): Ignore all XML attributes and only create\n text nodes.\n * `mergeAttrs` (default: `false`): Merge attributes and child elements as\n properties of the parent, instead of keying attributes off a child\n attribute object. This option is ignored if `ignoreAttrs` is `false`.\n * `validator` (default `null`): You can specify a callable that validates\n the resulting structure somehow, however you want. See unit tests\n for an example.\n * `xmlns` (default `false`): Give each element a field usually called '$ns'\n (the first character is the same as attrkey) that contains its local name\n and namespace URI.\n * `explicitChildren` (default `false`): Put child elements to separate\n property. Doesn't work with `mergeAttrs = true`. If element has no children\n then \"children\" won't be created. Added in 0.2.5.\n * `childkey` (default `$$`): Prefix that is used to access child elements if\n `explicitChildren` is set to `true`. Added in 0.2.5.\n * `preserveChildrenOrder` (default `false`): Modifies the behavior of\n `explicitChildren` so that the value of the \"children\" property becomes an\n ordered array. When this is `true`, every node will also get a `#name` field\n whose value will correspond to the XML nodeName, so that you may iterate\n the \"children\" array and still be able to determine node names. The named\n (and potentially unordered) properties are also retained in this\n configuration at the same level as the ordered \"children\" array. Added in\n 0.4.9.\n * `charsAsChildren` (default `false`): Determines whether chars should be\n considered children if `explicitChildren` is on. Added in 0.2.5.\n * `includeWhiteChars` (default `false`): Determines whether whitespace-only\n text nodes should be included. Added in 0.4.17.\n * `async` (default `false`): Should the callbacks be async? This *might* be\n an incompatible change if your code depends on sync execution of callbacks.\n Future versions of `xml2js` might change this default, so the recommendation\n is to not depend on sync execution anyway. Added in 0.2.6.\n * `strict` (default `true`): Set sax-js to strict or non-strict parsing mode.\n Defaults to `true` which is *highly* recommended, since parsing HTML which\n is not well-formed XML might yield just about anything. Added in 0.2.7.\n * `attrNameProcessors` (default: `null`): Allows the addition of attribute\n name processing functions. Accepts an `Array` of functions with following\n signature:\n ```javascript\n function (name){\n //do something with `name`\n return name\n }\n ```\n Added in 0.4.14\n * `attrValueProcessors` (default: `null`): Allows the addition of attribute\n value processing functions. Accepts an `Array` of functions with following\n signature:\n ```javascript\n function (name){\n //do something with `name`\n return name\n }\n ```\n Added in 0.4.1\n * `tagNameProcessors` (default: `null`): Allows the addition of tag name\n processing functions. Accepts an `Array` of functions with following\n signature:\n ```javascript\n function (name){\n //do something with `name`\n return name\n }\n ```\n Added in 0.4.1\n * `valueProcessors` (default: `null`): Allows the addition of element value\n processing functions. Accepts an `Array` of functions with following\n signature:\n ```javascript\n function (name){\n //do something with `name`\n return name\n }\n ```\n Added in 0.4.6\n\nOptions for the `Builder` class\n-------------------------------\nThese options are specified by ``new Builder({optionName: value})``.\nPossible options are:\n\n * `rootName` (default `root` or the root key name): root element name to be used in case\n `explicitRoot` is `false` or to override the root element name.\n * `renderOpts` (default `{ 'pretty': true, 'indent': ' ', 'newline': '\\n' }`):\n Rendering options for xmlbuilder-js.\n * pretty: prettify generated XML\n * indent: whitespace for indentation (only when pretty)\n * newline: newline char (only when pretty)\n * `xmldec` (default `{ 'version': '1.0', 'encoding': 'UTF-8', 'standalone': true }`:\n XML declaration attributes.\n * `xmldec.version` A version number string, e.g. 1.0\n * `xmldec.encoding` Encoding declaration, e.g. UTF-8\n * `xmldec.standalone` standalone document declaration: true or false\n * `doctype` (default `null`): optional DTD. Eg. `{'ext': 'hello.dtd'}`\n * `headless` (default: `false`): omit the XML header. Added in 0.4.3.\n * `allowSurrogateChars` (default: `false`): allows using characters from the Unicode\n surrogate blocks.\n * `cdata` (default: `false`): wrap text nodes in `<![CDATA[ ... ]]>` instead of\n escaping when necessary. Does not add `<![CDATA[ ... ]]>` if it is not required.\n Added in 0.4.5.\n\n`renderOpts`, `xmldec`,`doctype` and `headless` pass through to\n[xmlbuilder-js](https://github.com/oozcitak/xmlbuilder-js).\n\nUpdating to new version\n=======================\n\nVersion 0.2 changed the default parsing settings, but version 0.1.14 introduced\nthe default settings for version 0.2, so these settings can be tried before the\nmigration.\n\n```javascript\nvar xml2js = require('xml2js');\nvar parser = new xml2js.Parser(xml2js.defaults[\"0.2\"]);\n```\n\nTo get the 0.1 defaults in version 0.2 you can just use\n`xml2js.defaults[\"0.1\"]` in the same place. This provides you with enough time\nto migrate to the saner way of parsing in `xml2js` 0.2. We try to make the\nmigration as simple and gentle as possible, but some breakage cannot be\navoided.\n\nSo, what exactly did change and why? In 0.2 we changed some defaults to parse\nthe XML in a more universal and sane way. So we disabled `normalize` and `trim`\nso `xml2js` does not cut out any text content. You can reenable this at will of\ncourse. A more important change is that we return the root tag in the resulting\nJavaScript structure via the `explicitRoot` setting, so you need to access the\nfirst element. This is useful for anybody who wants to know what the root node\nis and preserves more information. The last major change was to enable\n`explicitArray`, so everytime it is possible that one might embed more than one\nsub-tag into a tag, xml2js >= 0.2 returns an array even if the array just\nincludes one element. This is useful when dealing with APIs that return\nvariable amounts of subtags.\n\nRunning tests, development\n==========================\n\n[![Build Status](https://travis-ci.org/Leonidas-from-XIV/node-xml2js.svg?branch=master)](https://travis-ci.org/Leonidas-from-XIV/node-xml2js)\n[![Coverage Status](https://coveralls.io/repos/Leonidas-from-XIV/node-xml2js/badge.svg?branch=)](https://coveralls.io/r/Leonidas-from-XIV/node-xml2js?branch=master)\n[![Dependency Status](https://david-dm.org/Leonidas-from-XIV/node-xml2js.svg)](https://david-dm.org/Leonidas-from-XIV/node-xml2js)\n\nThe development requirements are handled by npm, you just need to install them.\nWe also have a number of unit tests, they can be run using `npm test` directly\nfrom the project root. This runs zap to discover all the tests and execute\nthem.\n\nIf you like to contribute, keep in mind that `xml2js` is written in\nCoffeeScript, so don't develop on the JavaScript files that are checked into\nthe repository for convenience reasons. Also, please write some unit test to\ncheck your behaviour and if it is some user-facing thing, add some\ndocumentation to this README, so people will know it exists. Thanks in advance!\n\nGetting support\n===============\n\nPlease, if you have a problem with the library, first make sure you read this\nREADME. If you read this far, thanks, you're good. Then, please make sure your\nproblem really is with `xml2js`. It is? Okay, then I'll look at it. Send me a\nmail and we can talk. Please don't open issues, as I don't think that is the\nproper forum for support problems. Some problems might as well really be bugs\nin `xml2js`, if so I'll let you know to open an issue instead :)\n\nBut if you know you really found a bug, feel free to open an issue instead.\n",
  304 + "readmeFilename": "README.md",
  305 + "repository": {
  306 + "type": "git",
  307 + "url": "git+https://github.com/Leonidas-from-XIV/node-xml2js.git"
  308 + },
  309 + "scripts": {
  310 + "coverage": "nyc npm test && nyc report",
  311 + "coveralls": "nyc npm test && nyc report --reporter=text-lcov | coveralls",
  312 + "test": "zap"
  313 + },
  314 + "version": "0.4.19"
  315 +}
  1 +.travis.yml
  2 +src
  3 +test
  4 +perf
  5 +coverage
  1 +# Change Log
  2 +
  3 +All notable changes to this project are documented in this file. This project adheres to [Semantic Versioning](http://semver.org/#semantic-versioning-200).
  4 +
  5 +## [9.0.4] - 2017-08-16
  6 +- `spacebeforeslash` writer option accepts `true` as well as space char(s).
  7 +
  8 +## [9.0.3] - 2017-08-15
  9 +- `spacebeforeslash` writer option can now be used with XML fragments.
  10 +
  11 +## [9.0.2] - 2017-08-15
  12 +- Added the `spacebeforeslash` writer option to add a space character before closing tags of empty elements. See
  13 +[#157](https://github.com/oozcitak/xmlbuilder-js/issues/157).
  14 +
  15 +## [9.0.1] - 2017-06-19
  16 +- Fixed character validity checks to work with node.js 4.0 and 5.0. See
  17 +[#161](https://github.com/oozcitak/xmlbuilder-js/issues/161).
  18 +
  19 +## [9.0.0] - 2017-05-05
  20 +- Removed case conversion options.
  21 +- Removed support for node.js 4.0 and 5.0. Minimum required version is now 6.0.
  22 +- Fixed valid char filter to use XML 1.1 instead of 1.0. See
  23 +[#147](https://github.com/oozcitak/xmlbuilder-js/issues/147).
  24 +- Added options for negative indentation and suppressing pretty printing of text
  25 +nodes. See
  26 +[#145](https://github.com/oozcitak/xmlbuilder-js/issues/145).
  27 +
  28 +## [8.2.2] - 2016-04-08
  29 +- Falsy values can now be used as a text node in callback mode.
  30 +
  31 +## [8.2.1] - 2016-04-07
  32 +- Falsy values can now be used as a text node. See
  33 +[#117](https://github.com/oozcitak/xmlbuilder-js/issues/117).
  34 +
  35 +## [8.2.0] - 2016-04-01
  36 +- Removed lodash dependency to keep the library small and simple. See
  37 +[#114](https://github.com/oozcitak/xmlbuilder-js/issues/114),
  38 +[#53](https://github.com/oozcitak/xmlbuilder-js/issues/53),
  39 +and [#43](https://github.com/oozcitak/xmlbuilder-js/issues/43).
  40 +- Added title case to name conversion options.
  41 +
  42 +## [8.1.0] - 2016-03-29
  43 +- Added the callback option to the `begin` export function. When used with a
  44 +callback function, the XML document will be generated in chunks and each chunk
  45 +will be passed to the supplied function. In this mode, `begin` uses a different
  46 +code path and the builder should use much less memory since the entire XML tree
  47 +is not kept. There are a few drawbacks though. For example, traversing the document
  48 +tree or adding attributes to a node after it is written is not possible. It is
  49 +also not possible to remove nodes or attributes.
  50 +
  51 +``` js
  52 +var result = '';
  53 +
  54 +builder.begin(function(chunk) { result += chunk; })
  55 + .dec()
  56 + .ele('root')
  57 + .ele('xmlbuilder').up()
  58 + .end();
  59 +```
  60 +
  61 +- Replaced native `Object.assign` with `lodash.assign` to support old JS engines. See [#111](https://github.com/oozcitak/xmlbuilder-js/issues/111).
  62 +
  63 +## [8.0.0] - 2016-03-25
  64 +- Added the `begin` export function. See the wiki for details.
  65 +- Added the ability to add comments and processing instructions before and after the root element. Added `commentBefore`, `commentAfter`, `instructionBefore` and `instructionAfter` functions for this purpose.
  66 +- Dropped support for old node.js releases. Minimum required node.js version is now 4.0.
  67 +
  68 +## [7.0.0] - 2016-03-21
  69 +- Processing instructions are now created as regular nodes. This is a major breaking change if you are using processing instructions. Previously processing instructions were inserted before their parent node. After this change processing instructions are appended to the children of the parent node. Note that it is not currently possible to insert processing instructions before or after the root element.
  70 +```js
  71 +root.ele('node').ins('pi');
  72 +// pre-v7
  73 +<?pi?><node/>
  74 +// v7
  75 +<node><?pi?></node>
  76 +```
  77 +
  78 +## [6.0.0] - 2016-03-20
  79 +- Added custom XML writers. The default string conversion functions are now collected under the `XMLStringWriter` class which can be accessed by the `stringWriter(options)` function exported by the module. An `XMLStreamWriter` is also added which outputs the XML document to a writable stream. A stream writer can be created by calling the `streamWriter(stream, options)` function exported by the module. Both classes are heavily customizable and the details are added to the wiki. It is also possible to write an XML writer from scratch and use it when calling `end()` on the XML document.
  80 +
  81 +## [5.0.1] - 2016-03-08
  82 +- Moved require statements for text case conversion to the top of files to reduce lazy requires.
  83 +
  84 +## [5.0.0] - 2016-03-05
  85 +- Added text case option for element names and attribute names. Valid cases are `lower`, `upper`, `camel`, `kebab` and `snake`.
  86 +- Attribute and element values are escaped according to the [Canonical XML 1.0 specification](http://www.w3.org/TR/2000/WD-xml-c14n-20000119.html#charescaping). See [#54](https://github.com/oozcitak/xmlbuilder-js/issues/54) and [#86](https://github.com/oozcitak/xmlbuilder-js/issues/86).
  87 +- Added the `allowEmpty` option to `end()`. When this option is set, empty elements are not self-closed.
  88 +- Added support for [nested CDATA](https://en.wikipedia.org/wiki/CDATA#Nesting). The triad `]]>` in CDATA is now automatically replaced with `]]]]><![CDATA[>`.
  89 +
  90 +## [4.2.1] - 2016-01-15
  91 +- Updated lodash dependency to 4.0.0.
  92 +
  93 +## [4.2.0] - 2015-12-16
  94 +- Added the `noDoubleEncoding` option to `create()` to control whether existing html entities are encoded.
  95 +
  96 +## [4.1.0] - 2015-11-11
  97 +- Added the `separateArrayItems` option to `create()` to control how arrays are handled when converting from objects. e.g.
  98 +
  99 +```js
  100 +root.ele({ number: [ "one", "two" ]});
  101 +// with separateArrayItems: true
  102 +<number>
  103 + <one/>
  104 + <two/>
  105 +</number>
  106 +// with separateArrayItems: false
  107 +<number>one</number>
  108 +<number>two</number>
  109 +```
  110 +
  111 +## [4.0.0] - 2015-11-01
  112 +- Removed the `#list` decorator. Array items are now created as child nodes by default.
  113 +- Fixed a bug where the XML encoding string was checked partially.
  114 +
  115 +## [3.1.0] - 2015-09-19
  116 +- `#list` decorator ignores empty arrays.
  117 +
  118 +## [3.0.0] - 2015-09-10
  119 +- Allow `\r`, `\n` and `\t` in attribute values without escaping. See [#86](https://github.com/oozcitak/xmlbuilder-js/issues/86).
  120 +
  121 +## [2.6.5] - 2015-09-09
  122 +- Use native `isArray` instead of lodash.
  123 +- Indentation of processing instructions are set to the parent element's.
  124 +
  125 +## [2.6.4] - 2015-05-27
  126 +- Updated lodash dependency to 3.5.0.
  127 +
  128 +## [2.6.3] - 2015-05-27
  129 +- Bumped version because previous release was not published on npm.
  130 +
  131 +## [2.6.2] - 2015-03-10
  132 +- Updated lodash dependency to 3.5.0.
  133 +
  134 +## [2.6.1] - 2015-02-20
  135 +- Updated lodash dependency to 3.3.0.
  136 +
  137 +## [2.6.0] - 2015-02-20
  138 +- Fixed a bug where the `XMLNode` constructor overwrote the super class parent.
  139 +- Removed document property from cloned nodes.
  140 +- Switched to mocha.js for testing.
  141 +
  142 +## [2.5.2] - 2015-02-16
  143 +- Updated lodash dependency to 3.2.0.
  144 +
  145 +## [2.5.1] - 2015-02-09
  146 +- Updated lodash dependency to 3.1.0.
  147 +- Support all node >= 0.8.
  148 +
  149 +## [2.5.0] - 2015-00-03
  150 +- Updated lodash dependency to 3.0.0.
  151 +
  152 +## [2.4.6] - 2015-01-26
  153 +- Show more information from attribute creation with null values.
  154 +- Added iojs as an engine.
  155 +- Self close elements with empty text.
  156 +
  157 +## [2.4.5] - 2014-11-15
  158 +- Fixed prepublish script to run on windows.
  159 +- Fixed bug in XMLStringifier where an undefined value was used while reporting an invalid encoding value.
  160 +- Moved require statements to the top of files to reduce lazy requires. See [#62](https://github.com/oozcitak/xmlbuilder-js/issues/62).
  161 +
  162 +## [2.4.4] - 2014-09-08
  163 +- Added the `offset` option to `toString()` for use in XML fragments.
  164 +
  165 +## [2.4.3] - 2014-08-13
  166 +- Corrected license in package description.
  167 +
  168 +## [2.4.2] - 2014-08-13
  169 +- Dropped performance test and memwatch dependency.
  170 +
  171 +## [2.4.1] - 2014-08-12
  172 +- Fixed a bug where empty indent string was omitted when pretty printing. See [#59](https://github.com/oozcitak/xmlbuilder-js/issues/59).
  173 +
  174 +## [2.4.0] - 2014-08-04
  175 +- Correct cases of pubID and sysID.
  176 +- Use single lodash instead of separate npm modules. See [#53](https://github.com/oozcitak/xmlbuilder-js/issues/53).
  177 +- Escape according to Canonical XML 1.0. See [#54](https://github.com/oozcitak/xmlbuilder-js/issues/54).
  178 +
  179 +## [2.3.0] - 2014-07-17
  180 +- Convert objects to JS primitives while sanitizing user input.
  181 +- Object builder preserves items with null values. See [#44](https://github.com/oozcitak/xmlbuilder-js/issues/44).
  182 +- Use modularized lodash functions to cut down dependencies.
  183 +- Process empty objects when converting from objects so that we don't throw on empty child objects.
  184 +
  185 +## [2.2.1] - 2014-04-04
  186 +- Bumped version because previous release was not published on npm.
  187 +
  188 +## [2.2.0] - 2014-04-04
  189 +- Switch to lodash from underscore.
  190 +- Removed legacy `ext` option from `create()`.
  191 +- Drop old node versions: 0.4, 0.5, 0.6. 0.8 is the minimum requirement from now on.
  192 +
  193 +## [2.1.0] - 2013-12-30
  194 +- Removed duplicate null checks from constructors.
  195 +- Fixed node count in performance test.
  196 +- Added option for skipping null attribute values. See [#26](https://github.com/oozcitak/xmlbuilder-js/issues/26).
  197 +- Allow multiple values in `att()` and `ins()`.
  198 +- Added ability to run individual performance tests.
  199 +- Added flag for ignoring decorator strings.
  200 +
  201 +## [2.0.1] - 2013-12-24
  202 +- Removed performance tests from npm package.
  203 +
  204 +## [2.0.0] - 2013-12-24
  205 +- Combined loops for speed up.
  206 +- Added support for the DTD and XML declaration.
  207 +- `clone` includes attributes.
  208 +- Added performance tests.
  209 +- Evaluate attribute value if function.
  210 +- Evaluate instruction value if function.
  211 +
  212 +## [1.1.2] - 2013-12-11
  213 +- Changed processing instruction decorator to `?`.
  214 +
  215 +## [1.1.1] - 2013-12-11
  216 +- Added processing instructions to JS object conversion.
  217 +
  218 +## [1.1.0] - 2013-12-10
  219 +- Added license to package.
  220 +- `create()` and `element()` accept JS object to fully build the document.
  221 +- Added `nod()` and `n()` aliases for `node()`.
  222 +- Renamed `convertAttChar` decorator to `convertAttKey`.
  223 +- Ignore empty decorator strings when converting JS objects.
  224 +
  225 +## [1.0.2] - 2013-11-27
  226 +- Removed temp file which was accidentally included in the package.
  227 +
  228 +## [1.0.1] - 2013-11-27
  229 +- Custom stringify functions affect current instance only.
  230 +
  231 +## [1.0.0] - 2013-11-27
  232 +- Added processing instructions.
  233 +- Added stringify functions to sanitize and convert input values.
  234 +- Added option for headless XML documents.
  235 +- Added vows tests.
  236 +- Removed Makefile. Using npm publish scripts instead.
  237 +- Removed the `begin()` function. `create()` begins the document by creating the root node.
  238 +
  239 +## [0.4.3] - 2013-11-08
  240 +- Added option to include surrogate pairs in XML content. See [#29](https://github.com/oozcitak/xmlbuilder-js/issues/29).
  241 +- Fixed empty value string representation in pretty mode.
  242 +- Added pre and postpublish scripts to package.json.
  243 +- Filtered out prototype properties when appending attributes. See [#31](https://github.com/oozcitak/xmlbuilder-js/issues/31).
  244 +
  245 +## [0.4.2] - 2012-09-14
  246 +- Removed README.md from `.npmignore`.
  247 +
  248 +## [0.4.1] - 2012-08-31
  249 +- Removed `begin()` calls in favor of `XMLBuilder` constructor.
  250 +- Added the `end()` function. `end()` is a convenience over `doc().toString()`.
  251 +
  252 +## [0.4.0] - 2012-08-31
  253 +- Added arguments to `XMLBuilder` constructor to allow the name of the root element and XML prolog to be defined in one line.
  254 +- Soft deprecated `begin()`.
  255 +
  256 +## [0.3.11] - 2012-08-13
  257 +- Package keywords are fixed to be an array of values.
  258 +
  259 +## [0.3.10] - 2012-08-13
  260 +- Brought back npm package contents which were lost due to incorrect configuration of `package.json` in previous releases.
  261 +
  262 +## [0.3.3] - 2012-07-27
  263 +- Implemented `importXMLBuilder()`.
  264 +
  265 +## [0.3.2] - 2012-07-20
  266 +- Fixed a duplicated escaping problem on `element()`.
  267 +- Fixed a problem with text node creation from empty string.
  268 +- Calling `root()` on the document element returns the root element.
  269 +- `XMLBuilder` no longer extends `XMLFragment`.
  270 +
  271 +## [0.3.1] - 2011-11-28
  272 +- Added guards for document element so that nodes cannot be inserted at document level.
  273 +
  274 +## [0.3.0] - 2011-11-28
  275 +- Added `doc()` to return the document element.
  276 +
  277 +## [0.2.2] - 2011-11-28
  278 +- Prevent code relying on `up()`'s older behavior to break.
  279 +
  280 +## [0.2.1] - 2011-11-28
  281 +- Added the `root()` function.
  282 +
  283 +## [0.2.0] - 2011-11-21
  284 +- Added Travis-CI integration.
  285 +- Added coffee-script dependency.
  286 +- Added insert, traversal and delete functions.
  287 +
  288 +## [0.1.7] - 2011-10-25
  289 +- No changes. Accidental release.
  290 +
  291 +## [0.1.6] - 2011-10-25
  292 +- Corrected `package.json` bugs link to `url` from `web`.
  293 +
  294 +## [0.1.5] - 2011-08-08
  295 +- Added missing npm package contents.
  296 +
  297 +## [0.1.4] - 2011-07-29
  298 +- Text-only nodes are no longer indented.
  299 +- Added documentation for multiple instances.
  300 +
  301 +## [0.1.3] - 2011-07-27
  302 +- Exported the `create()` function to return a new instance. This allows multiple builder instances to be constructed.
  303 +- Fixed `u()` function so that it now correctly calls `up()`.
  304 +- Fixed typo in `element()` so that `attributes` and `text` can be passed interchangeably.
  305 +
  306 +## [0.1.2] - 2011-06-03
  307 +- `ele()` accepts element text.
  308 +- `attributes()` now overrides existing attributes if passed the same attribute name.
  309 +
  310 +## [0.1.1] - 2011-05-19
  311 +- Added the raw output option.
  312 +- Removed most validity checks.
  313 +
  314 +## [0.1.0] - 2011-04-27
  315 +- `text()` and `cdata()` now return parent element.
  316 +- Attribute values are escaped.
  317 +
  318 +## [0.0.7] - 2011-04-23
  319 +- Coerced text values to string.
  320 +
  321 +## [0.0.6] - 2011-02-23
  322 +- Added support for XML comments.
  323 +- Text nodes are checked against CharData.
  324 +
  325 +## [0.0.5] - 2010-12-31
  326 +- Corrected the name of the main npm module in `package.json`.
  327 +
  328 +## [0.0.4] - 2010-12-28
  329 +- Added `.npmignore`.
  330 +
  331 +## [0.0.3] - 2010-12-27
  332 +- root element is now constructed in `begin()`.
  333 +- moved prolog to `begin()`.
  334 +- Added the ability to have CDATA in element text.
  335 +- Removed unused prolog aliases.
  336 +- Removed `builder()` function from main module.
  337 +- Added the name of the main npm module in `package.json`.
  338 +
  339 +## [0.0.2] - 2010-11-03
  340 +- `element()` expands nested arrays.
  341 +- Added pretty printing.
  342 +- Added the `up()`, `build()` and `prolog()` functions.
  343 +- Added readme.
  344 +
  345 +## 0.0.1 - 2010-11-02
  346 +- Initial release
  347 +
  348 +[9.0.4]: https://github.com/oozcitak/xmlbuilder-js/compare/v9.0.3...v9.0.4
  349 +[9.0.3]: https://github.com/oozcitak/xmlbuilder-js/compare/v9.0.2...v9.0.3
  350 +[9.0.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v9.0.1...v9.0.2
  351 +[9.0.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v9.0.0...v9.0.1
  352 +[9.0.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v8.2.2...v9.0.0
  353 +[8.2.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v8.2.1...v8.2.2
  354 +[8.2.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v8.2.0...v8.2.1
  355 +[8.2.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v8.1.0...v8.2.0
  356 +[8.1.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v8.0.0...v8.1.0
  357 +[8.0.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v7.0.0...v8.0.0
  358 +[7.0.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v6.0.0...v7.0.0
  359 +[6.0.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v5.0.1...v6.0.0
  360 +[5.0.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v5.0.0...v5.0.1
  361 +[5.0.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v4.2.1...v5.0.0
  362 +[4.2.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v4.2.0...v4.2.1
  363 +[4.2.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v4.1.0...v4.2.0
  364 +[4.1.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v4.0.0...v4.1.0
  365 +[4.0.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v3.1.0...v4.0.0
  366 +[3.1.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v3.0.0...v3.1.0
  367 +[3.0.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.6.5...v3.0.0
  368 +[2.6.5]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.6.4...v2.6.5
  369 +[2.6.4]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.6.3...v2.6.4
  370 +[2.6.3]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.6.2...v2.6.3
  371 +[2.6.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.6.1...v2.6.2
  372 +[2.6.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.6.0...v2.6.1
  373 +[2.6.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.5.2...v2.6.0
  374 +[2.5.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.5.1...v2.5.2
  375 +[2.5.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.5.0...v2.5.1
  376 +[2.5.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.4.6...v2.5.0
  377 +[2.4.6]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.4.5...v2.4.6
  378 +[2.4.5]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.4.4...v2.4.5
  379 +[2.4.4]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.4.3...v2.4.4
  380 +[2.4.3]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.4.2...v2.4.3
  381 +[2.4.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.4.1...v2.4.2
  382 +[2.4.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.4.0...v2.4.1
  383 +[2.4.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.3.0...v2.4.0
  384 +[2.3.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.2.1...v2.3.0
  385 +[2.2.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.2.0...v2.2.1
  386 +[2.2.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.1.0...v2.2.0
  387 +[2.1.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.0.1...v2.1.0
  388 +[2.0.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v2.0.0...v2.0.1
  389 +[2.0.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v1.1.2...v2.0.0
  390 +[1.1.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v1.1.1...v1.1.2
  391 +[1.1.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v1.1.0...v1.1.1
  392 +[1.1.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v1.0.2...v1.1.0
  393 +[1.0.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v1.0.1...v1.0.2
  394 +[1.0.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v1.0.0...v1.0.1
  395 +[1.0.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.4.3...v1.0.0
  396 +[0.4.3]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.4.2...v0.4.3
  397 +[0.4.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.4.1...v0.4.2
  398 +[0.4.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.4.0...v0.4.1
  399 +[0.4.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.3.11...v0.4.0
  400 +[0.3.11]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.3.10...v0.3.11
  401 +[0.3.10]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.3.3...v0.3.10
  402 +[0.3.3]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.3.2...v0.3.3
  403 +[0.3.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.3.1...v0.3.2
  404 +[0.3.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.3.0...v0.3.1
  405 +[0.3.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.2.2...v0.3.0
  406 +[0.2.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.2.1...v0.2.2
  407 +[0.2.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.2.0...v0.2.1
  408 +[0.2.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.1.7...v0.2.0
  409 +[0.1.7]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.1.6...v0.1.7
  410 +[0.1.6]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.1.5...v0.1.6
  411 +[0.1.5]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.1.4...v0.1.5
  412 +[0.1.4]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.1.3...v0.1.4
  413 +[0.1.3]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.1.2...v0.1.3
  414 +[0.1.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.1.1...v0.1.2
  415 +[0.1.1]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.1.0...v0.1.1
  416 +[0.1.0]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.0.7...v0.1.0
  417 +[0.0.7]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.0.6...v0.0.7
  418 +[0.0.6]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.0.5...v0.0.6
  419 +[0.0.5]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.0.4...v0.0.5
  420 +[0.0.4]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.0.3...v0.0.4
  421 +[0.0.3]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.0.2...v0.0.3
  422 +[0.0.2]: https://github.com/oozcitak/xmlbuilder-js/compare/v0.0.1...v0.0.2
  423 +
  1 +The MIT License (MIT)
  2 +
  3 +Copyright (c) 2013 Ozgur Ozcitak
  4 +
  5 +Permission is hereby granted, free of charge, to any person obtaining a copy
  6 +of this software and associated documentation files (the "Software"), to deal
  7 +in the Software without restriction, including without limitation the rights
  8 +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9 +copies of the Software, and to permit persons to whom the Software is
  10 +furnished to do so, subject to the following conditions:
  11 +
  12 +The above copyright notice and this permission notice shall be included in
  13 +all copies or substantial portions of the Software.
  14 +
  15 +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16 +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17 +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18 +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19 +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20 +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21 +THE SOFTWARE.
  1 +# xmlbuilder-js
  2 +
  3 +An XML builder for [node.js](https://nodejs.org/) similar to
  4 +[java-xmlbuilder](https://github.com/jmurty/java-xmlbuilder).
  5 +
  6 +[![License](http://img.shields.io/npm/l/xmlbuilder.svg?style=flat-square)](http://opensource.org/licenses/MIT)
  7 +[![NPM Version](http://img.shields.io/npm/v/xmlbuilder.svg?style=flat-square)](https://npmjs.com/package/xmlbuilder)
  8 +[![NPM Downloads](https://img.shields.io/npm/dm/xmlbuilder.svg?style=flat-square)](https://npmjs.com/package/xmlbuilder)
  9 +
  10 +[![Build Status](http://img.shields.io/travis/oozcitak/xmlbuilder-js.svg?style=flat-square)](http://travis-ci.org/oozcitak/xmlbuilder-js)
  11 +[![Dev Dependency Status](http://img.shields.io/david/dev/oozcitak/xmlbuilder-js.svg?style=flat-square)](https://david-dm.org/oozcitak/xmlbuilder-js)
  12 +[![Code Coverage](https://img.shields.io/coveralls/oozcitak/xmlbuilder-js.svg?style=flat-square)](https://coveralls.io/github/oozcitak/xmlbuilder-js)
  13 +
  14 +### Installation:
  15 +
  16 +``` sh
  17 +npm install xmlbuilder
  18 +```
  19 +
  20 +### Usage:
  21 +
  22 +``` js
  23 +var builder = require('xmlbuilder');
  24 +var xml = builder.create('root')
  25 + .ele('xmlbuilder')
  26 + .ele('repo', {'type': 'git'}, 'git://github.com/oozcitak/xmlbuilder-js.git')
  27 + .end({ pretty: true});
  28 +
  29 +console.log(xml);
  30 +```
  31 +
  32 +will result in:
  33 +
  34 +``` xml
  35 +<?xml version="1.0"?>
  36 +<root>
  37 + <xmlbuilder>
  38 + <repo type="git">git://github.com/oozcitak/xmlbuilder-js.git</repo>
  39 + </xmlbuilder>
  40 +</root>
  41 +```
  42 +
  43 +It is also possible to convert objects into nodes:
  44 +
  45 +``` js
  46 +builder.create({
  47 + root: {
  48 + xmlbuilder: {
  49 + repo: {
  50 + '@type': 'git', // attributes start with @
  51 + '#text': 'git://github.com/oozcitak/xmlbuilder-js.git' // text node
  52 + }
  53 + }
  54 + }
  55 +});
  56 +```
  57 +
  58 +If you need to do some processing:
  59 +
  60 +``` js
  61 +var root = builder.create('squares');
  62 +root.com('f(x) = x^2');
  63 +for(var i = 1; i <= 5; i++)
  64 +{
  65 + var item = root.ele('data');
  66 + item.att('x', i);
  67 + item.att('y', i * i);
  68 +}
  69 +```
  70 +
  71 +This will result in:
  72 +
  73 +``` xml
  74 +<?xml version="1.0"?>
  75 +<squares>
  76 + <!-- f(x) = x^2 -->
  77 + <data x="1" y="1"/>
  78 + <data x="2" y="4"/>
  79 + <data x="3" y="9"/>
  80 + <data x="4" y="16"/>
  81 + <data x="5" y="25"/>
  82 +</squares>
  83 +```
  84 +
  85 +See the [wiki](https://github.com/oozcitak/xmlbuilder-js/wiki) for details and [examples](https://github.com/oozcitak/xmlbuilder-js/wiki/Examples) for more complex examples.
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var assign, isArray, isEmpty, isFunction, isObject, isPlainObject,
  4 + slice = [].slice,
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + assign = function() {
  8 + var i, key, len, source, sources, target;
  9 + target = arguments[0], sources = 2 <= arguments.length ? slice.call(arguments, 1) : [];
  10 + if (isFunction(Object.assign)) {
  11 + Object.assign.apply(null, arguments);
  12 + } else {
  13 + for (i = 0, len = sources.length; i < len; i++) {
  14 + source = sources[i];
  15 + if (source != null) {
  16 + for (key in source) {
  17 + if (!hasProp.call(source, key)) continue;
  18 + target[key] = source[key];
  19 + }
  20 + }
  21 + }
  22 + }
  23 + return target;
  24 + };
  25 +
  26 + isFunction = function(val) {
  27 + return !!val && Object.prototype.toString.call(val) === '[object Function]';
  28 + };
  29 +
  30 + isObject = function(val) {
  31 + var ref;
  32 + return !!val && ((ref = typeof val) === 'function' || ref === 'object');
  33 + };
  34 +
  35 + isArray = function(val) {
  36 + if (isFunction(Array.isArray)) {
  37 + return Array.isArray(val);
  38 + } else {
  39 + return Object.prototype.toString.call(val) === '[object Array]';
  40 + }
  41 + };
  42 +
  43 + isEmpty = function(val) {
  44 + var key;
  45 + if (isArray(val)) {
  46 + return !val.length;
  47 + } else {
  48 + for (key in val) {
  49 + if (!hasProp.call(val, key)) continue;
  50 + return false;
  51 + }
  52 + return true;
  53 + }
  54 + };
  55 +
  56 + isPlainObject = function(val) {
  57 + var ctor, proto;
  58 + return isObject(val) && (proto = Object.getPrototypeOf(val)) && (ctor = proto.constructor) && (typeof ctor === 'function') && (ctor instanceof ctor) && (Function.prototype.toString.call(ctor) === Function.prototype.toString.call(Object));
  59 + };
  60 +
  61 + module.exports.assign = assign;
  62 +
  63 + module.exports.isFunction = isFunction;
  64 +
  65 + module.exports.isObject = isObject;
  66 +
  67 + module.exports.isArray = isArray;
  68 +
  69 + module.exports.isEmpty = isEmpty;
  70 +
  71 + module.exports.isPlainObject = isPlainObject;
  72 +
  73 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var XMLAttribute;
  4 +
  5 + module.exports = XMLAttribute = (function() {
  6 + function XMLAttribute(parent, name, value) {
  7 + this.options = parent.options;
  8 + this.stringify = parent.stringify;
  9 + if (name == null) {
  10 + throw new Error("Missing attribute name of element " + parent.name);
  11 + }
  12 + if (value == null) {
  13 + throw new Error("Missing attribute value for attribute " + name + " of element " + parent.name);
  14 + }
  15 + this.name = this.stringify.attName(name);
  16 + this.value = this.stringify.attValue(value);
  17 + }
  18 +
  19 + XMLAttribute.prototype.clone = function() {
  20 + return Object.create(this);
  21 + };
  22 +
  23 + XMLAttribute.prototype.toString = function(options) {
  24 + return this.options.writer.set(options).attribute(this);
  25 + };
  26 +
  27 + return XMLAttribute;
  28 +
  29 + })();
  30 +
  31 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var XMLCData, XMLNode,
  4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + XMLNode = require('./XMLNode');
  8 +
  9 + module.exports = XMLCData = (function(superClass) {
  10 + extend(XMLCData, superClass);
  11 +
  12 + function XMLCData(parent, text) {
  13 + XMLCData.__super__.constructor.call(this, parent);
  14 + if (text == null) {
  15 + throw new Error("Missing CDATA text");
  16 + }
  17 + this.text = this.stringify.cdata(text);
  18 + }
  19 +
  20 + XMLCData.prototype.clone = function() {
  21 + return Object.create(this);
  22 + };
  23 +
  24 + XMLCData.prototype.toString = function(options) {
  25 + return this.options.writer.set(options).cdata(this);
  26 + };
  27 +
  28 + return XMLCData;
  29 +
  30 + })(XMLNode);
  31 +
  32 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var XMLComment, XMLNode,
  4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + XMLNode = require('./XMLNode');
  8 +
  9 + module.exports = XMLComment = (function(superClass) {
  10 + extend(XMLComment, superClass);
  11 +
  12 + function XMLComment(parent, text) {
  13 + XMLComment.__super__.constructor.call(this, parent);
  14 + if (text == null) {
  15 + throw new Error("Missing comment text");
  16 + }
  17 + this.text = this.stringify.comment(text);
  18 + }
  19 +
  20 + XMLComment.prototype.clone = function() {
  21 + return Object.create(this);
  22 + };
  23 +
  24 + XMLComment.prototype.toString = function(options) {
  25 + return this.options.writer.set(options).comment(this);
  26 + };
  27 +
  28 + return XMLComment;
  29 +
  30 + })(XMLNode);
  31 +
  32 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var XMLDTDAttList, XMLNode,
  4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + XMLNode = require('./XMLNode');
  8 +
  9 + module.exports = XMLDTDAttList = (function(superClass) {
  10 + extend(XMLDTDAttList, superClass);
  11 +
  12 + function XMLDTDAttList(parent, elementName, attributeName, attributeType, defaultValueType, defaultValue) {
  13 + XMLDTDAttList.__super__.constructor.call(this, parent);
  14 + if (elementName == null) {
  15 + throw new Error("Missing DTD element name");
  16 + }
  17 + if (attributeName == null) {
  18 + throw new Error("Missing DTD attribute name");
  19 + }
  20 + if (!attributeType) {
  21 + throw new Error("Missing DTD attribute type");
  22 + }
  23 + if (!defaultValueType) {
  24 + throw new Error("Missing DTD attribute default");
  25 + }
  26 + if (defaultValueType.indexOf('#') !== 0) {
  27 + defaultValueType = '#' + defaultValueType;
  28 + }
  29 + if (!defaultValueType.match(/^(#REQUIRED|#IMPLIED|#FIXED|#DEFAULT)$/)) {
  30 + throw new Error("Invalid default value type; expected: #REQUIRED, #IMPLIED, #FIXED or #DEFAULT");
  31 + }
  32 + if (defaultValue && !defaultValueType.match(/^(#FIXED|#DEFAULT)$/)) {
  33 + throw new Error("Default value only applies to #FIXED or #DEFAULT");
  34 + }
  35 + this.elementName = this.stringify.eleName(elementName);
  36 + this.attributeName = this.stringify.attName(attributeName);
  37 + this.attributeType = this.stringify.dtdAttType(attributeType);
  38 + this.defaultValue = this.stringify.dtdAttDefault(defaultValue);
  39 + this.defaultValueType = defaultValueType;
  40 + }
  41 +
  42 + XMLDTDAttList.prototype.toString = function(options) {
  43 + return this.options.writer.set(options).dtdAttList(this);
  44 + };
  45 +
  46 + return XMLDTDAttList;
  47 +
  48 + })(XMLNode);
  49 +
  50 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var XMLDTDElement, XMLNode,
  4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + XMLNode = require('./XMLNode');
  8 +
  9 + module.exports = XMLDTDElement = (function(superClass) {
  10 + extend(XMLDTDElement, superClass);
  11 +
  12 + function XMLDTDElement(parent, name, value) {
  13 + XMLDTDElement.__super__.constructor.call(this, parent);
  14 + if (name == null) {
  15 + throw new Error("Missing DTD element name");
  16 + }
  17 + if (!value) {
  18 + value = '(#PCDATA)';
  19 + }
  20 + if (Array.isArray(value)) {
  21 + value = '(' + value.join(',') + ')';
  22 + }
  23 + this.name = this.stringify.eleName(name);
  24 + this.value = this.stringify.dtdElementValue(value);
  25 + }
  26 +
  27 + XMLDTDElement.prototype.toString = function(options) {
  28 + return this.options.writer.set(options).dtdElement(this);
  29 + };
  30 +
  31 + return XMLDTDElement;
  32 +
  33 + })(XMLNode);
  34 +
  35 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var XMLDTDEntity, XMLNode, isObject,
  4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + isObject = require('./Utility').isObject;
  8 +
  9 + XMLNode = require('./XMLNode');
  10 +
  11 + module.exports = XMLDTDEntity = (function(superClass) {
  12 + extend(XMLDTDEntity, superClass);
  13 +
  14 + function XMLDTDEntity(parent, pe, name, value) {
  15 + XMLDTDEntity.__super__.constructor.call(this, parent);
  16 + if (name == null) {
  17 + throw new Error("Missing entity name");
  18 + }
  19 + if (value == null) {
  20 + throw new Error("Missing entity value");
  21 + }
  22 + this.pe = !!pe;
  23 + this.name = this.stringify.eleName(name);
  24 + if (!isObject(value)) {
  25 + this.value = this.stringify.dtdEntityValue(value);
  26 + } else {
  27 + if (!value.pubID && !value.sysID) {
  28 + throw new Error("Public and/or system identifiers are required for an external entity");
  29 + }
  30 + if (value.pubID && !value.sysID) {
  31 + throw new Error("System identifier is required for a public external entity");
  32 + }
  33 + if (value.pubID != null) {
  34 + this.pubID = this.stringify.dtdPubID(value.pubID);
  35 + }
  36 + if (value.sysID != null) {
  37 + this.sysID = this.stringify.dtdSysID(value.sysID);
  38 + }
  39 + if (value.nData != null) {
  40 + this.nData = this.stringify.dtdNData(value.nData);
  41 + }
  42 + if (this.pe && this.nData) {
  43 + throw new Error("Notation declaration is not allowed in a parameter entity");
  44 + }
  45 + }
  46 + }
  47 +
  48 + XMLDTDEntity.prototype.toString = function(options) {
  49 + return this.options.writer.set(options).dtdEntity(this);
  50 + };
  51 +
  52 + return XMLDTDEntity;
  53 +
  54 + })(XMLNode);
  55 +
  56 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var XMLDTDNotation, XMLNode,
  4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + XMLNode = require('./XMLNode');
  8 +
  9 + module.exports = XMLDTDNotation = (function(superClass) {
  10 + extend(XMLDTDNotation, superClass);
  11 +
  12 + function XMLDTDNotation(parent, name, value) {
  13 + XMLDTDNotation.__super__.constructor.call(this, parent);
  14 + if (name == null) {
  15 + throw new Error("Missing notation name");
  16 + }
  17 + if (!value.pubID && !value.sysID) {
  18 + throw new Error("Public or system identifiers are required for an external entity");
  19 + }
  20 + this.name = this.stringify.eleName(name);
  21 + if (value.pubID != null) {
  22 + this.pubID = this.stringify.dtdPubID(value.pubID);
  23 + }
  24 + if (value.sysID != null) {
  25 + this.sysID = this.stringify.dtdSysID(value.sysID);
  26 + }
  27 + }
  28 +
  29 + XMLDTDNotation.prototype.toString = function(options) {
  30 + return this.options.writer.set(options).dtdNotation(this);
  31 + };
  32 +
  33 + return XMLDTDNotation;
  34 +
  35 + })(XMLNode);
  36 +
  37 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var XMLDeclaration, XMLNode, isObject,
  4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + isObject = require('./Utility').isObject;
  8 +
  9 + XMLNode = require('./XMLNode');
  10 +
  11 + module.exports = XMLDeclaration = (function(superClass) {
  12 + extend(XMLDeclaration, superClass);
  13 +
  14 + function XMLDeclaration(parent, version, encoding, standalone) {
  15 + var ref;
  16 + XMLDeclaration.__super__.constructor.call(this, parent);
  17 + if (isObject(version)) {
  18 + ref = version, version = ref.version, encoding = ref.encoding, standalone = ref.standalone;
  19 + }
  20 + if (!version) {
  21 + version = '1.0';
  22 + }
  23 + this.version = this.stringify.xmlVersion(version);
  24 + if (encoding != null) {
  25 + this.encoding = this.stringify.xmlEncoding(encoding);
  26 + }
  27 + if (standalone != null) {
  28 + this.standalone = this.stringify.xmlStandalone(standalone);
  29 + }
  30 + }
  31 +
  32 + XMLDeclaration.prototype.toString = function(options) {
  33 + return this.options.writer.set(options).declaration(this);
  34 + };
  35 +
  36 + return XMLDeclaration;
  37 +
  38 + })(XMLNode);
  39 +
  40 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var XMLDTDAttList, XMLDTDElement, XMLDTDEntity, XMLDTDNotation, XMLDocType, XMLNode, isObject,
  4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + isObject = require('./Utility').isObject;
  8 +
  9 + XMLNode = require('./XMLNode');
  10 +
  11 + XMLDTDAttList = require('./XMLDTDAttList');
  12 +
  13 + XMLDTDEntity = require('./XMLDTDEntity');
  14 +
  15 + XMLDTDElement = require('./XMLDTDElement');
  16 +
  17 + XMLDTDNotation = require('./XMLDTDNotation');
  18 +
  19 + module.exports = XMLDocType = (function(superClass) {
  20 + extend(XMLDocType, superClass);
  21 +
  22 + function XMLDocType(parent, pubID, sysID) {
  23 + var ref, ref1;
  24 + XMLDocType.__super__.constructor.call(this, parent);
  25 + this.documentObject = parent;
  26 + if (isObject(pubID)) {
  27 + ref = pubID, pubID = ref.pubID, sysID = ref.sysID;
  28 + }
  29 + if (sysID == null) {
  30 + ref1 = [pubID, sysID], sysID = ref1[0], pubID = ref1[1];
  31 + }
  32 + if (pubID != null) {
  33 + this.pubID = this.stringify.dtdPubID(pubID);
  34 + }
  35 + if (sysID != null) {
  36 + this.sysID = this.stringify.dtdSysID(sysID);
  37 + }
  38 + }
  39 +
  40 + XMLDocType.prototype.element = function(name, value) {
  41 + var child;
  42 + child = new XMLDTDElement(this, name, value);
  43 + this.children.push(child);
  44 + return this;
  45 + };
  46 +
  47 + XMLDocType.prototype.attList = function(elementName, attributeName, attributeType, defaultValueType, defaultValue) {
  48 + var child;
  49 + child = new XMLDTDAttList(this, elementName, attributeName, attributeType, defaultValueType, defaultValue);
  50 + this.children.push(child);
  51 + return this;
  52 + };
  53 +
  54 + XMLDocType.prototype.entity = function(name, value) {
  55 + var child;
  56 + child = new XMLDTDEntity(this, false, name, value);
  57 + this.children.push(child);
  58 + return this;
  59 + };
  60 +
  61 + XMLDocType.prototype.pEntity = function(name, value) {
  62 + var child;
  63 + child = new XMLDTDEntity(this, true, name, value);
  64 + this.children.push(child);
  65 + return this;
  66 + };
  67 +
  68 + XMLDocType.prototype.notation = function(name, value) {
  69 + var child;
  70 + child = new XMLDTDNotation(this, name, value);
  71 + this.children.push(child);
  72 + return this;
  73 + };
  74 +
  75 + XMLDocType.prototype.toString = function(options) {
  76 + return this.options.writer.set(options).docType(this);
  77 + };
  78 +
  79 + XMLDocType.prototype.ele = function(name, value) {
  80 + return this.element(name, value);
  81 + };
  82 +
  83 + XMLDocType.prototype.att = function(elementName, attributeName, attributeType, defaultValueType, defaultValue) {
  84 + return this.attList(elementName, attributeName, attributeType, defaultValueType, defaultValue);
  85 + };
  86 +
  87 + XMLDocType.prototype.ent = function(name, value) {
  88 + return this.entity(name, value);
  89 + };
  90 +
  91 + XMLDocType.prototype.pent = function(name, value) {
  92 + return this.pEntity(name, value);
  93 + };
  94 +
  95 + XMLDocType.prototype.not = function(name, value) {
  96 + return this.notation(name, value);
  97 + };
  98 +
  99 + XMLDocType.prototype.up = function() {
  100 + return this.root() || this.documentObject;
  101 + };
  102 +
  103 + return XMLDocType;
  104 +
  105 + })(XMLNode);
  106 +
  107 +}).call(this);
  1 +// Generated by CoffeeScript 1.12.6
  2 +(function() {
  3 + var XMLDocument, XMLNode, XMLStringWriter, XMLStringifier, isPlainObject,
  4 + extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
  5 + hasProp = {}.hasOwnProperty;
  6 +
  7 + isPlainObject = require('./Utility').isPlainObject;
  8 +
  9 + XMLNode = require('./XMLNode');
  10 +
  11 + XMLStringifier = require('./XMLStringifier');
  12 +
  13 + XMLStringWriter = require('./XMLStringWriter');
  14 +
  15 + module.exports = XMLDocument = (function(superClass) {
  16 + extend(XMLDocument, superClass);
  17 +
  18 + function XMLDocument(options) {
  19 + XMLDocument.__super__.constructor.call(this, null);
  20 + options || (options = {});
  21 + if (!options.writer) {
  22 + options.writer = new XMLStringWriter();
  23 + }
  24 + this.options = options;
  25 + this.stringify = new XMLStringifier(options);
  26 + this.isDocument = true;
  27 + }
  28 +
  29 + XMLDocument.prototype.end = function(writer) {
  30 + var writerOptions;
  31 + if (!writer) {
  32 + writer = this.options.writer;
  33 + } else if (isPlainObject(writer)) {
  34 + writerOptions = writer;
  35 + writer = this.options.writer.set(writerOptions);
  36 + }
  37 + return writer.document(this);
  38 + };
  39 +
  40 + XMLDocument.prototype.toString = function(options) {
  41 + return this.options.writer.set(options).document(this);
  42 + };
  43 +
  44 + return XMLDocument;
  45 +
  46 + })(XMLNode);
  47 +
  48 +}).call(this);