• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

sile-typesetter / sile / 12272864087

11 Dec 2024 08:55AM UTC coverage: 29.607% (-41.0%) from 70.614%
12272864087

push

github

web-flow
Merge 95cccf286 into f394f608c

5834 of 19705 relevant lines covered (29.61%)

429.05 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/packages/bibtex/csl/utils/xmlparser.lua
1
--- Modified XML parser
2
--
3
-- MOSTLY ADAPTED FROM SILE's XML INPUTTER
4
-- BUT WITH EXTRA FEATURES FOR NAMESPACING AND SPACES CLEANING.
5
--
6
-- It simplifies the processing a lot later...
7
-- TODO FIXME: This could raise an interesting discussion about the supposedly
8
-- generic XML support in SILE...
9

10
local lxp = require("lxp")
×
11

12
local defaultRules = {
×
13
   -- NAMESPACING:
14
   -- If defined, prefix is prepended to the tag name to create the SILE
15
   -- command name.
16
   -- This is a way to avoid conflicts between different XML formats and
17
   -- SILE commands.
18
   prefix = nil,
19
   -- SPACES CLEANING:
20
   -- Depending on the XML schema, some spaces may be irrelevant.
21
   -- Some XML nodes are containers for other nodes. They may have spaces
22
   -- in their content, due to the XML formatting and indentation.
23
   -- Some XML nodes contain text that should be stripped of trailing and
24
   -- leading spaces.
25
   -- It is cumbersome to have to strip spaces in the SILE content later,
26
   -- so we can define here the nodes for which we want to strip spaces.
27
   -- skipEmptyStrings is eitheir a boolean or a table with tags to skip
28
   -- text strings composed only of spaces in elements.
29
   -- When set to true, all elements are considered by default. In that
30
   -- case, preserveEmptyStrings is used to keep empty strings in some
31
   -- elements.
32
   -- stripSpaces is either a boolean or a table with tags to strip the
33
   -- leading and trailing spaces in text elements.
34
   -- When set to true, all elements are considered by default. In that
35
   -- case, preserveSpaces is used to keep spaces in some tags.
36
   stripSpaces = false,
37
   preserveSpaces = {},
38
   skipEmptyStrings = false,
39
   preserveEmptyStrings = {},
40
}
41

42
local function isStripSpaces (tag, rules)
43
   if type(rules.stripSpaces) == "table" then
×
44
      return rules.stripSpaces[tag] and not rules.preserveSpaces[tag]
×
45
   end
46
   return rules.stripSpaces and not rules.preserveSpaces[tag]
×
47
end
48

49
local function isSkipEmptyStrings (tag, rules)
50
   if type(rules.skipEmptyStrings) == "table" then
×
51
      return rules.skipEmptyStrings[tag] and not rules.preserveEmptyStrings[tag]
×
52
   end
53
   return rules.skipEmptyStrings and not rules.preserveEmptyStrings[tag]
×
54
end
55

56
local function startcommand (parser, command, options)
57
   local callback = parser:getcallbacks()
×
58
   local stack = callback.stack
×
59
   local lno, col, pos = parser:pos()
×
60
   local position = { lno = lno, col = col, pos = pos }
×
61
   -- create an empty command which content will be filled on closing tag
62
   local element = SU.ast.createCommand(command, options, nil, position)
×
63
   table.insert(stack, element)
×
64
end
65

66
local function endcommand (parser, command)
67
   local callback = parser:getcallbacks()
×
68
   local stack, rules = callback.stack, callback.rules
×
69
   local element = table.remove(stack)
×
70
   assert(element.command == command)
×
71
   element.command = rules.prefix and (rules.prefix .. command) or command
×
72

73
   local level = #stack
×
74
   table.insert(stack[level], element)
×
75
end
76

77
local function text (parser, msg)
78
   local callback = parser:getcallbacks()
×
79
   local stack, rules = callback.stack, callback.rules
×
80
   local element = stack[#stack]
×
81

82
   local stripSpaces = isStripSpaces(element.command, rules)
×
83
   local skipEmptyStrings = isSkipEmptyStrings(element.command, rules)
×
84

85
   local txt = (stripSpaces or skipEmptyStrings) and msg:gsub("^%s+", ""):gsub("%s+$", "") or msg
×
86
   if skipEmptyStrings and txt == "" then
×
87
      return
×
88
   end
89
   msg = stripSpaces and txt or msg
×
90

91
   local n = #element
×
92
   if type(element[n]) == "string" then
×
93
      element[n] = element[n] .. msg
×
94
   else
95
      table.insert(element, msg)
×
96
   end
97
end
98

99
local function parse (doc, rules)
100
   local content = {
×
101
      StartElement = startcommand,
102
      EndElement = endcommand,
103
      CharacterData = text,
104
      _nonstrict = true,
105
      stack = { {} },
106
      rules = rules or defaultRules,
107
   }
108
   local parser = lxp.new(content)
×
109
   local status, err
110
   if type(doc) == "string" then
×
111
      status, err = parser:parse(doc)
×
112
      if not status then
×
113
         return nil, err
×
114
      end
115
   else
116
      return nil, "Only string input should be supported"
×
117
   end
118
   status, err = parser:parse()
×
119
   if not status then
×
120
      return nil, err
×
121
   end
122
   parser:close()
×
123
   return content.stack[1][1]
×
124
end
125

126
return {
×
127
   parse = parse,
128
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc