my-dataentry
Version:
通用详情页功能组件
166 lines (147 loc) • 4.56 kB
JavaScript
let _order = 1
export default function t_xml (S) {
const openBracket = '<'
const openBracketCC = '<'.charCodeAt(0)
const closeBracket = '>'
const closeBracketCC = '>'.charCodeAt(0)
const minusCC = '-'.charCodeAt(0)
const slashCC = '/'.charCodeAt(0)
const exclamationCC = '!'.charCodeAt(0)
const singleQuoteCC = '\''.charCodeAt(0)
const doubleQuoteCC = '"'.charCodeAt(0)
const questionMarkCC = '?'.charCodeAt(0)
/**
* returns text until the first nonAlphebetic letter
*/
const nameSpacer = '\r\n\t>/= '
let pos = 0
/**
* Parsing a list of entries
*/
function parseChildren () {
const children = []
while (S[pos]) {
if (S.charCodeAt(pos) === openBracketCC) {
if (S.charCodeAt(pos + 1) === slashCC) { // </
// while (S[pos]!=='>') { pos++; }
pos = S.indexOf(closeBracket, pos)
return children
} else if (S.charCodeAt(pos + 1) === exclamationCC) { // <! or <!--
if (S.charCodeAt(pos + 2) === minusCC) {
// comment support
while (!(S.charCodeAt(pos) === closeBracketCC && S.charCodeAt(pos - 1) === minusCC &&
S.charCodeAt(pos - 2) === minusCC && pos !== -1)) {
pos = S.indexOf(closeBracket, pos + 1)
}
if (pos === -1) {
pos = S.length
}
} else {
// doctype support
pos += 2
for (; S.charCodeAt(pos) !== closeBracketCC; pos++) {}
}
pos++
continue
} else if (S.charCodeAt(pos + 1) === questionMarkCC) { // <?
// XML header support
pos = S.indexOf(closeBracket, pos)
pos++
continue
}
pos++
let startNamePos = pos
for (; nameSpacer.indexOf(S[pos]) === -1; pos++) {}
const nodeTagName = S.slice(startNamePos, pos)
// Parsing attributes
let attrFound = false
let nodeAttributes = {}
for (; S.charCodeAt(pos) !== closeBracketCC; pos++) {
const c = S.charCodeAt(pos)
if ((c > 64 && c < 91) || (c > 96 && c < 123)) {
startNamePos = pos
for (; nameSpacer.indexOf(S[pos]) === -1; pos++) {}
const name = S.slice(startNamePos, pos)
// search beginning of the string
let code = S.charCodeAt(pos)
while (code !== singleQuoteCC && code !== doubleQuoteCC) {
pos++
code = S.charCodeAt(pos)
}
const startChar = S[pos]
const startStringPos = ++pos
pos = S.indexOf(startChar, startStringPos)
const value = S.slice(startStringPos, pos)
if (!attrFound) {
nodeAttributes = {}
attrFound = true
}
nodeAttributes[name] = value
}
}
// Optional parsing of children
let nodeChildren
if (S.charCodeAt(pos - 1) !== slashCC) {
pos++
nodeChildren = parseChildren()
}
children.push({
'children': nodeChildren,
'tagName': nodeTagName,
'attrs': nodeAttributes
})
} else {
const startTextPos = pos
pos = S.indexOf(openBracket, pos) - 1 // Skip characters until '<'
if (pos === -2) {
pos = S.length
}
const text = S.slice(startTextPos, pos + 1)
if (text.trim().length > 0) {
children.push(text)
}
}
pos++
}
return children
}
_order = 1
return simplefy(parseChildren())
}
function simplefy (children) {
const node = {}
if (children === undefined) {
return {}
}
// Text node (e.g. <t>This is text.</t>)
if (children.length === 1 && (typeof children[0] === 'string' || children[0] instanceof String)) {
// eslint-disable-next-line no-new-wrappers
return new String(children[0])
}
// map each object
children.forEach(function (child) {
if (!node[child.tagName]) {
node[child.tagName] = []
}
if (typeof child === 'object') {
const kids = simplefy(child.children)
if (child.attrs) {
kids.attrs = child.attrs
}
if (kids['attrs'] === undefined) {
kids['attrs'] = {'order': _order}
} else {
kids['attrs']['order'] = _order
}
_order++
node[child.tagName].push(kids)
}
})
for (let i in node) {
if (node[i].length === 1) {
node[i] = node[i][0]
}
}
return node
}