質問編集履歴
3
`concat\(\)` で連結するコードで `"""` を指定すると `concat\(\)` がエラーを返すバグ修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -102,6 +102,8 @@
|
|
102
102
|
|
103
103
|
<li>"</li>
|
104
104
|
|
105
|
+
<li>"""</li>
|
106
|
+
|
105
107
|
<li>"""x"""</li>
|
106
108
|
|
107
109
|
<li>"hoge"</li>
|
@@ -144,9 +146,9 @@
|
|
144
146
|
|
145
147
|
|
146
148
|
|
147
|
-
if (string
|
149
|
+
if (/^"+$/g.test(string)) {
|
148
|
-
|
150
|
+
|
149
|
-
return '\u0027
|
151
|
+
return '\u0027' + string + '\u0027';
|
150
152
|
|
151
153
|
}
|
152
154
|
|
@@ -192,6 +194,8 @@
|
|
192
194
|
|
193
195
|
console.log(toXPathStringLiteral('"')); // '"'
|
194
196
|
|
197
|
+
console.log(toXPathStringLiteral('"""')); // '"""'
|
198
|
+
|
195
199
|
console.log(toXPathStringLiteral('"""x"""')); // concat('"""',"x",'"""')
|
196
200
|
|
197
201
|
console.log(toXPathStringLiteral('"hoge"')); // concat('"',"hoge",'"')
|
@@ -206,6 +210,8 @@
|
|
206
210
|
|
207
211
|
console.log(getFirstTextNode(ul, '"')); // "
|
208
212
|
|
213
|
+
console.log(getFirstTextNode(ul, '"""')); // """
|
214
|
+
|
209
215
|
console.log(getFirstTextNode(ul, '"""x"""')); // """x"""
|
210
216
|
|
211
217
|
console.log(getFirstTextNode(ul, '"hoge"')); // "hoge"
|
@@ -217,3 +223,15 @@
|
|
217
223
|
</script>
|
218
224
|
|
219
225
|
```
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
### 更新履歴
|
230
|
+
|
231
|
+
|
232
|
+
|
233
|
+
- 2016/04/10 10:01 `getFirstTextNode` における `evaluate` の第2引数が `ul` になっていたので `contextNode` に修正
|
234
|
+
|
235
|
+
- 2016/04/10 12:05 `concat()` で連結するコードを追記 (CertaiN さん発案)
|
236
|
+
|
237
|
+
- 2016/04/11 09:50 `concat()` で連結するコードで `"""` を指定すると `concat()` がエラーを返すバグ修正
|
2
concat\(\) で連結するコードを追記 \(CertaiN さん発案\)
test
CHANGED
File without changes
|
test
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
### 質問
|
2
|
+
|
3
|
+
|
4
|
+
|
1
5
|
- [XPath 式でテキストノード値を指定してフィルタするには?(31198)|teratail](https://teratail.com/questions/31198)
|
2
6
|
|
3
7
|
|
@@ -64,7 +68,7 @@
|
|
64
68
|
|
65
69
|
function getFirstTextNode (contextNode, string) {
|
66
70
|
|
67
|
-
return document.evaluate('descendant::text()[.="' + String(string).replace(/"/g, '""') + '"]',
|
71
|
+
return document.evaluate('descendant::text()[.="' + String(string).replace(/"/g, '""') + '"]', contextNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
68
72
|
|
69
73
|
}
|
70
74
|
|
@@ -79,3 +83,137 @@
|
|
79
83
|
|
80
84
|
|
81
85
|
XPath でダブルクォート(`"`)をエスケープするにはどんな方法が考えられるでしょうか。
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
### (解決案) concat() で連結する
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
CertaiN さんに XPath 式の `concat()` 関数で連結する方法を教えて頂きました。
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
```HTML
|
98
|
+
|
99
|
+
<ul id="sample">
|
100
|
+
|
101
|
+
<li>test</li>
|
102
|
+
|
103
|
+
<li>"</li>
|
104
|
+
|
105
|
+
<li>"""x"""</li>
|
106
|
+
|
107
|
+
<li>"hoge"</li>
|
108
|
+
|
109
|
+
<li>'foo'</li>
|
110
|
+
|
111
|
+
<li>"piyo'</li>
|
112
|
+
|
113
|
+
</ul>
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
<script>
|
118
|
+
|
119
|
+
'use strict';
|
120
|
+
|
121
|
+
var toXPathStringLiteral = (function () {
|
122
|
+
|
123
|
+
function replacefn (match, p1) {
|
124
|
+
|
125
|
+
|
126
|
+
|
127
|
+
if (p1) {
|
128
|
+
|
129
|
+
return ',\u0027' + p1 + '\u0027';
|
130
|
+
|
131
|
+
}
|
132
|
+
|
133
|
+
|
134
|
+
|
135
|
+
return ',"' + match + '"';
|
136
|
+
|
137
|
+
}
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
return function toXPathStringLiteral (string) {
|
142
|
+
|
143
|
+
string = String(string);
|
144
|
+
|
145
|
+
|
146
|
+
|
147
|
+
if (string === '"') {
|
148
|
+
|
149
|
+
return '\u0027"\u0027';
|
150
|
+
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
switch (string.indexOf('"')) {
|
156
|
+
|
157
|
+
case -1:
|
158
|
+
|
159
|
+
return '"' + string + '"';
|
160
|
+
|
161
|
+
case 0:
|
162
|
+
|
163
|
+
return 'concat(' + string.replace(/("+)|[^"]+/g, replacefn).slice(1) + ')';
|
164
|
+
|
165
|
+
default:
|
166
|
+
|
167
|
+
return 'concat(' + string.replace(/("+)|[^"]+/g, replacefn) + ')';
|
168
|
+
|
169
|
+
}
|
170
|
+
|
171
|
+
};
|
172
|
+
|
173
|
+
}());
|
174
|
+
|
175
|
+
|
176
|
+
|
177
|
+
|
178
|
+
|
179
|
+
function getFirstTextNode (contextNode, string) {
|
180
|
+
|
181
|
+
return document.evaluate('descendant::text()[.=' + toXPathStringLiteral(string) + ']', contextNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
182
|
+
|
183
|
+
}
|
184
|
+
|
185
|
+
|
186
|
+
|
187
|
+
var ul = document.getElementById('sample');
|
188
|
+
|
189
|
+
|
190
|
+
|
191
|
+
console.log(toXPathStringLiteral('test')); // "test"
|
192
|
+
|
193
|
+
console.log(toXPathStringLiteral('"')); // '"'
|
194
|
+
|
195
|
+
console.log(toXPathStringLiteral('"""x"""')); // concat('"""',"x",'"""')
|
196
|
+
|
197
|
+
console.log(toXPathStringLiteral('"hoge"')); // concat('"',"hoge",'"')
|
198
|
+
|
199
|
+
console.log(toXPathStringLiteral('\u0027foo\u0027')); // "'foo'"
|
200
|
+
|
201
|
+
console.log(toXPathStringLiteral('"piyo\u0027')); // concat('"',"piyo'")
|
202
|
+
|
203
|
+
|
204
|
+
|
205
|
+
console.log(getFirstTextNode(ul, 'test')); // test
|
206
|
+
|
207
|
+
console.log(getFirstTextNode(ul, '"')); // "
|
208
|
+
|
209
|
+
console.log(getFirstTextNode(ul, '"""x"""')); // """x"""
|
210
|
+
|
211
|
+
console.log(getFirstTextNode(ul, '"hoge"')); // "hoge"
|
212
|
+
|
213
|
+
console.log(getFirstTextNode(ul, '\u0027foo\u0027')); // 'foo'
|
214
|
+
|
215
|
+
console.log(getFirstTextNode(ul, '"piyo\u0027')); // "piyo'
|
216
|
+
|
217
|
+
</script>
|
218
|
+
|
219
|
+
```
|
1
contextNode の変数指定ミス修正
test
CHANGED
File without changes
|
test
CHANGED
@@ -26,7 +26,7 @@
|
|
26
26
|
|
27
27
|
function getFirstTextNode (contextNode, string) {
|
28
28
|
|
29
|
-
return document.evaluate('descendant::text()[.="' + String(string) + '"]',
|
29
|
+
return document.evaluate('descendant::text()[.="' + String(string).replace(/"/g, '""') + '"]', contextNode, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
|
30
30
|
|
31
31
|
}
|
32
32
|
|