1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 | package Torello.HTML;
import Torello.HTML.helper.AttrRegEx;
import Torello.Java.StringParse;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.stream.Stream;
class RetrieveAllAttr
{
static Properties allAV(
final TagNode tn,
final boolean keepQuotes,
final boolean preserveKeysCase
)
{
Properties ret = new Properties();
// NOTE: OPTIMIZED, "closing-versions" of the TagNode, and TagNode's whose 'str' field is
// is only longer than the token, itself, by 3 or less characters cannot have
// attributes.
// CHARS: '<', TOKEN, SPACE, '>'
// RET: In that case, just return an empty 'Properties' instance.
if (tn.isClosing || (tn.str.length() <= (tn.tok.length() + 3))) return ret;
// This RegEx Matcher 'matches' against Attribute/InnerTag Key-Value Pairs.
// m.group(1): UN-USED! (Includes Key, Equals-Sign, and Value). Not w/leading white-space
// m.group(2): returns the 'key' portion of the key-value pair, before an '=' (equals-sign)
// m.group(3): returns the 'value' portion of the key-value pair, after an '='
Matcher m = AttrRegEx.KEY_VALUE_REGEX.matcher(tn.str);
// MORE-CODE, but MORE-EFFICIENT (slightly)
if (keepQuotes && preserveKeysCase)
while (m.find()) ret.put(m.group(2), m.group(3));
else if (!keepQuotes && preserveKeysCase)
while (m.find()) ret.put(m.group(2), StringParse.ifQuotesStripQuotes(m.group(3)));
else if (keepQuotes && !preserveKeysCase)
while (m.find()) ret.put(m.group(2).toLowerCase(), m.group(3));
else if (!keepQuotes && !preserveKeysCase)
while (m.find())
ret.put(m.group(2).toLowerCase(), StringParse.ifQuotesStripQuotes(m.group(3)));
return ret;
}
public static Stream<String> allAN(
final TagNode tn,
final boolean preserveKeysCase,
final boolean includeKeyOnlyAttributes
)
{
// If there is NO ROOM in the "str" field for attributes, then there is now way attributes
// could exist in this element. Return "empty" immediately.
//
// NOTE: OPTIMIZED, "closing-versions" of the TagNode, and TagNode's whose 'str' field
// is only longer than the token, itself, by 3 or less characters cannot have
// attributes.
//
// CHARS: '<', TOKEN, SPACE, '>'
// RET: In that case, just return an empty Stream.
if (tn.isClosing || (tn.str.length() <= (tn.tok.length() + 3))) return Stream.empty();
// Use Java Streams. A String-Stream is easily converted to just about any data-type
Stream.Builder<String> b = Stream.builder();
// This RegEx Matcher 'matches' against Attribute/InnerTag Key-Value Pairs.
// m.group(2): returns the 'key' portion of the key-value pair, before an '=' (equals-sign)
Matcher m = AttrRegEx.KEY_VALUE_REGEX.matcher(tn.str);
// Retrieve all of the keys of the attribute key-value pairs.
while (m.find()) b.add(m.group(2));
// This Stream contains only keys that were once key-value pairs, if there are "key-only"
// attributes, they have not been added yet.
Stream<String> ret = b.build();
// Convert these to lower-case, (if requested)
if (! preserveKeysCase) ret = ret.map((String attribute) -> attribute.toLowerCase());
// Now, add in all the "Key-Only" attributes (if there are any). Note, "preserve-case"
// and "to lower case" are handled, already, in method "allKeyOnlyAttributes(boolean)"
if (includeKeyOnlyAttributes)
return Stream.concat
(ret, KeyOnlyAttributes.allKeyOnlyAttributes(tn, preserveKeysCase));
return ret;
}
}
|