View Javadoc
1   /*
2    * Copyright (c) 2002-2017 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * http://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package com.gargoylesoftware.htmlunit.html;
16  
17  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.KEYGEN_AS_BLOCK;
18  import static com.gargoylesoftware.htmlunit.BrowserVersionFeatures.KEYGEN_AS_SELECT;
19  
20  import java.util.Arrays;
21  import java.util.LinkedHashMap;
22  import java.util.List;
23  import java.util.Locale;
24  import java.util.Map;
25  
26  import org.xml.sax.Attributes;
27  
28  import com.gargoylesoftware.htmlunit.BrowserVersion;
29  import com.gargoylesoftware.htmlunit.SgmlPage;
30  import com.gargoylesoftware.htmlunit.javascript.configuration.JavaScriptConfiguration;
31  
32  /**
33   * Element factory which creates elements by calling the constructor on a
34   * given {@link HtmlElement} subclass.
35   * The constructor is expected to take 2 arguments of type
36   * {@link HtmlPage} and {@link java.util.Map}
37   * where the first one is the owning page of the element, the second one is a map
38   * holding the initial attributes for the element.
39   *
40   * @author <a href="mailto:cse@dynabean.de">Christian Sell</a>
41   * @author Ahmed Ashour
42   * @author David K. Taylor
43   * @author Ronald Brill
44   * @author Frank Danek
45   */
46  class DefaultElementFactory implements ElementFactory {
47  
48      private static final String KEYGEN_ = "keygen";
49  
50      /*
51       * You can generate your own test cases by looking into ElementTestSource.generateTestForHtmlElements
52       */
53      static final List<String> SUPPORTED_TAGS_ = Arrays.asList(KEYGEN_, HtmlAbbreviated.TAG_NAME, HtmlAcronym.TAG_NAME,
54              HtmlAnchor.TAG_NAME, HtmlAddress.TAG_NAME, HtmlApplet.TAG_NAME, HtmlArea.TAG_NAME,
55              HtmlArticle.TAG_NAME, HtmlAside.TAG_NAME, HtmlAudio.TAG_NAME,
56              HtmlBackgroundSound.TAG_NAME, HtmlBase.TAG_NAME, HtmlBaseFont.TAG_NAME,
57              HtmlBidirectionalIsolation.TAG_NAME, HtmlBidirectionalOverride.TAG_NAME, HtmlBig.TAG_NAME,
58              HtmlBlink.TAG_NAME, HtmlBlockQuote.TAG_NAME, HtmlBody.TAG_NAME, HtmlBold.TAG_NAME,
59              HtmlBreak.TAG_NAME, HtmlButton.TAG_NAME, HtmlCanvas.TAG_NAME, HtmlCaption.TAG_NAME,
60              HtmlCenter.TAG_NAME, HtmlCitation.TAG_NAME, HtmlCode.TAG_NAME,
61              HtmlCommand.TAG_NAME, HtmlContent.TAG_NAME, HtmlData.TAG_NAME, HtmlDataList.TAG_NAME,
62              HtmlDefinition.TAG_NAME, HtmlDefinitionDescription.TAG_NAME,
63              HtmlDeletedText.TAG_NAME, HtmlDetails.TAG_NAME, HtmlDialog.TAG_NAME, HtmlDirectory.TAG_NAME,
64              HtmlDivision.TAG_NAME, HtmlDefinitionList.TAG_NAME,
65              HtmlDefinitionTerm.TAG_NAME, HtmlEmbed.TAG_NAME,
66              HtmlEmphasis.TAG_NAME,
67              HtmlFieldSet.TAG_NAME, HtmlFigureCaption.TAG_NAME, HtmlFigure.TAG_NAME,
68              HtmlFont.TAG_NAME, HtmlForm.TAG_NAME, HtmlFooter.TAG_NAME,
69              HtmlFrame.TAG_NAME, HtmlFrameSet.TAG_NAME,
70              HtmlHead.TAG_NAME, HtmlHeader.TAG_NAME,
71              HtmlHeading1.TAG_NAME, HtmlHeading2.TAG_NAME, HtmlHeading3.TAG_NAME,
72              HtmlHeading4.TAG_NAME, HtmlHeading5.TAG_NAME, HtmlHeading6.TAG_NAME,
73              HtmlHorizontalRule.TAG_NAME, HtmlHtml.TAG_NAME, HtmlInlineFrame.TAG_NAME,
74              HtmlInlineQuotation.TAG_NAME,
75              HtmlImage.TAG_NAME, HtmlImage.TAG_NAME2, HtmlInsertedText.TAG_NAME, HtmlIsIndex.TAG_NAME,
76              HtmlItalic.TAG_NAME,
77              HtmlKeyboard.TAG_NAME, HtmlLabel.TAG_NAME, HtmlLayer.TAG_NAME,
78              HtmlLegend.TAG_NAME, HtmlListing.TAG_NAME, HtmlListItem.TAG_NAME,
79              HtmlLink.TAG_NAME, HtmlMain.TAG_NAME, HtmlMap.TAG_NAME, HtmlMark.TAG_NAME, HtmlMarquee.TAG_NAME,
80              HtmlMenu.TAG_NAME, HtmlMenuItem.TAG_NAME, HtmlMeta.TAG_NAME, HtmlMeter.TAG_NAME, HtmlMultiColumn.TAG_NAME,
81              HtmlNav.TAG_NAME, HtmlNextId.TAG_NAME,
82              HtmlNoBreak.TAG_NAME, HtmlNoEmbed.TAG_NAME, HtmlNoFrames.TAG_NAME,
83              HtmlNoLayer.TAG_NAME,
84              HtmlNoScript.TAG_NAME, HtmlObject.TAG_NAME, HtmlOrderedList.TAG_NAME,
85              HtmlOptionGroup.TAG_NAME, HtmlOption.TAG_NAME, HtmlOutput.TAG_NAME,
86              HtmlParagraph.TAG_NAME,
87              HtmlParameter.TAG_NAME, HtmlPicture.TAG_NAME, HtmlPlainText.TAG_NAME, HtmlPreformattedText.TAG_NAME,
88              HtmlProgress.TAG_NAME,
89              HtmlRp.TAG_NAME, HtmlRt.TAG_NAME, HtmlRuby.TAG_NAME,
90              HtmlS.TAG_NAME, HtmlSample.TAG_NAME,
91              HtmlScript.TAG_NAME, HtmlSection.TAG_NAME, HtmlSelect.TAG_NAME, HtmlSlot.TAG_NAME, HtmlSmall.TAG_NAME,
92              HtmlSource.TAG_NAME, HtmlSpan.TAG_NAME,
93              HtmlStrike.TAG_NAME, HtmlStrong.TAG_NAME, HtmlStyle.TAG_NAME,
94              HtmlSubscript.TAG_NAME, HtmlSummary.TAG_NAME, HtmlSuperscript.TAG_NAME,
95              HtmlSvg.TAG_NAME,
96              HtmlTable.TAG_NAME, HtmlTableColumn.TAG_NAME, HtmlTableColumnGroup.TAG_NAME,
97              HtmlTableBody.TAG_NAME, HtmlTableDataCell.TAG_NAME, HtmlTableHeaderCell.TAG_NAME,
98              HtmlTableRow.TAG_NAME, HtmlTextArea.TAG_NAME, HtmlTableFooter.TAG_NAME,
99              HtmlTableHeader.TAG_NAME, HtmlTeletype.TAG_NAME, HtmlTemplate.TAG_NAME, HtmlTime.TAG_NAME,
100             HtmlTitle.TAG_NAME, HtmlTrack.TAG_NAME, HtmlUnderlined.TAG_NAME, HtmlUnorderedList.TAG_NAME,
101             HtmlVariable.TAG_NAME, HtmlVideo.TAG_NAME, HtmlWordBreak.TAG_NAME, HtmlExample.TAG_NAME
102     );
103 
104     /**
105      * @param page the owning page
106      * @param tagName the HTML tag name
107      * @param attributes initial attributes, possibly {@code null}
108      * @return the newly created element
109      */
110     @Override
111     public HtmlElement createElement(final SgmlPage page, final String tagName, final Attributes attributes) {
112         return createElementNS(page, null, tagName, attributes);
113     }
114 
115     /**
116      * @param page the owning page
117      * @param namespaceURI the URI that identifies an XML namespace
118      * @param qualifiedName the qualified name of the element type to instantiate
119      * @param attributes initial attributes, possibly {@code null}
120      * @return the newly created element
121      */
122     @Override
123     public HtmlElement createElementNS(final SgmlPage page, final String namespaceURI,
124             final String qualifiedName, final Attributes attributes) {
125         return createElementNS(page, namespaceURI, qualifiedName, attributes, false);
126     }
127 
128     /**
129      * @param page the owning page
130      * @param namespaceURI the URI that identifies an XML namespace
131      * @param qualifiedName the qualified name of the element type to instantiate
132      * @param attributes initial attributes, possibly {@code null}
133      * @param checkBrowserCompatibility if true and the page doesn't support this element, return null
134      * @return the newly created element
135      */
136     @Override
137     public HtmlElement createElementNS(final SgmlPage page, final String namespaceURI,
138             final String qualifiedName, final Attributes attributes, final boolean checkBrowserCompatibility) {
139         final Map<String, DomAttr> attributeMap = toMap(page, attributes);
140 
141         final HtmlElement element;
142         final String tagName;
143         final int colonIndex = qualifiedName.indexOf(':');
144         if (colonIndex == -1) {
145             tagName = qualifiedName.toLowerCase(Locale.ROOT);
146         }
147         else {
148             tagName = qualifiedName.substring(colonIndex + 1).toLowerCase(Locale.ROOT);
149         }
150 
151         switch (tagName) {
152             case KEYGEN_:
153                 final BrowserVersion browserVersion = page.getWebClient().getBrowserVersion();
154                 if (browserVersion.hasFeature(KEYGEN_AS_BLOCK)) {
155                     element = new HtmlBlockQuote(qualifiedName, page, attributeMap);
156                 }
157                 else if (browserVersion.hasFeature(KEYGEN_AS_SELECT)) {
158                     element = new HtmlSpan(qualifiedName, page, attributeMap);
159                 }
160                 else {
161                     element = new HtmlUnknownElement(page, qualifiedName, attributeMap);
162                 }
163                 break;
164 
165             case HtmlAbbreviated.TAG_NAME:
166                 element = new HtmlAbbreviated(qualifiedName, page, attributeMap);
167                 break;
168 
169             case HtmlAcronym.TAG_NAME:
170                 element = new HtmlAcronym(qualifiedName, page, attributeMap);
171                 break;
172 
173             case HtmlAddress.TAG_NAME:
174                 element = new HtmlAddress(qualifiedName, page, attributeMap);
175                 break;
176 
177             case HtmlAnchor.TAG_NAME:
178                 element = new HtmlAnchor(qualifiedName, page, attributeMap);
179                 break;
180 
181             case HtmlApplet.TAG_NAME:
182                 element = new HtmlApplet(qualifiedName, page, attributeMap);
183                 break;
184 
185             case HtmlArea.TAG_NAME:
186                 element = new HtmlArea(qualifiedName, page, attributeMap);
187                 break;
188 
189             case HtmlArticle.TAG_NAME:
190                 element = new HtmlArticle(qualifiedName, page, attributeMap);
191                 break;
192 
193             case HtmlAside.TAG_NAME:
194                 element = new HtmlAside(qualifiedName, page, attributeMap);
195                 break;
196 
197             case HtmlAudio.TAG_NAME:
198                 element = new HtmlAudio(qualifiedName, page, attributeMap);
199                 break;
200 
201             case HtmlBackgroundSound.TAG_NAME:
202                 element = new HtmlBackgroundSound(qualifiedName, page, attributeMap);
203                 break;
204 
205             case HtmlBase.TAG_NAME:
206                 element = new HtmlBase(qualifiedName, page, attributeMap);
207                 break;
208 
209             case HtmlBaseFont.TAG_NAME:
210                 element = new HtmlBaseFont(qualifiedName, page, attributeMap);
211                 break;
212 
213             case HtmlBidirectionalIsolation.TAG_NAME:
214                 element = new HtmlBidirectionalIsolation(qualifiedName, page, attributeMap);
215                 break;
216 
217             case HtmlBidirectionalOverride.TAG_NAME:
218                 element = new HtmlBidirectionalOverride(qualifiedName, page, attributeMap);
219                 break;
220 
221             case HtmlBig.TAG_NAME:
222                 element = new HtmlBig(qualifiedName, page, attributeMap);
223                 break;
224 
225             case HtmlBlink.TAG_NAME:
226                 element = new HtmlBlink(qualifiedName, page, attributeMap);
227                 break;
228 
229             case HtmlBlockQuote.TAG_NAME:
230                 element = new HtmlBlockQuote(qualifiedName, page, attributeMap);
231                 break;
232 
233             case HtmlBody.TAG_NAME:
234                 element = new HtmlBody(qualifiedName, page, attributeMap, false);
235                 break;
236 
237             case HtmlBold.TAG_NAME:
238                 element = new HtmlBold(qualifiedName, page, attributeMap);
239                 break;
240 
241             case HtmlBreak.TAG_NAME:
242                 element = new HtmlBreak(qualifiedName, page, attributeMap);
243                 break;
244 
245             case HtmlButton.TAG_NAME:
246                 element = new HtmlButton(qualifiedName, page, attributeMap);
247                 break;
248 
249             case HtmlCanvas.TAG_NAME:
250                 element = new HtmlCanvas(qualifiedName, page, attributeMap);
251                 break;
252 
253             case HtmlCaption.TAG_NAME:
254                 element = new HtmlCaption(qualifiedName, page, attributeMap);
255                 break;
256 
257             case HtmlCenter.TAG_NAME:
258                 element = new HtmlCenter(qualifiedName, page, attributeMap);
259                 break;
260 
261             case HtmlCitation.TAG_NAME:
262                 element = new HtmlCitation(qualifiedName, page, attributeMap);
263                 break;
264 
265             case HtmlCode.TAG_NAME:
266                 element = new HtmlCode(qualifiedName, page, attributeMap);
267                 break;
268 
269             case HtmlCommand.TAG_NAME:
270                 element = new HtmlCommand(qualifiedName, page, attributeMap);
271                 break;
272 
273             case HtmlContent.TAG_NAME:
274                 element = new HtmlContent(qualifiedName, page, attributeMap);
275                 break;
276 
277             case HtmlData.TAG_NAME:
278                 element = new HtmlData(qualifiedName, page, attributeMap);
279                 break;
280 
281             case HtmlDataList.TAG_NAME:
282                 element = new HtmlDataList(qualifiedName, page, attributeMap);
283                 break;
284 
285             case HtmlDefinition.TAG_NAME:
286                 element = new HtmlDefinition(qualifiedName, page, attributeMap);
287                 break;
288 
289             case HtmlDefinitionDescription.TAG_NAME:
290                 element = new HtmlDefinitionDescription(qualifiedName, page, attributeMap);
291                 break;
292 
293             case HtmlDefinitionList.TAG_NAME:
294                 element = new HtmlDefinitionList(qualifiedName, page, attributeMap);
295                 break;
296 
297             case HtmlDefinitionTerm.TAG_NAME:
298                 element = new HtmlDefinitionTerm(qualifiedName, page, attributeMap);
299                 break;
300 
301             case HtmlDeletedText.TAG_NAME:
302                 element = new HtmlDeletedText(qualifiedName, page, attributeMap);
303                 break;
304 
305             case HtmlDetails.TAG_NAME:
306                 element = new HtmlDetails(qualifiedName, page, attributeMap);
307                 break;
308 
309             case HtmlDialog.TAG_NAME:
310                 element = new HtmlDialog(qualifiedName, page, attributeMap);
311                 break;
312 
313             case HtmlDirectory.TAG_NAME:
314                 element = new HtmlDirectory(qualifiedName, page, attributeMap);
315                 break;
316 
317             case HtmlDivision.TAG_NAME:
318                 element = new HtmlDivision(qualifiedName, page, attributeMap);
319                 break;
320 
321             case HtmlEmbed.TAG_NAME:
322                 element = new HtmlEmbed(qualifiedName, page, attributeMap);
323                 break;
324 
325             case HtmlEmphasis.TAG_NAME:
326                 element = new HtmlEmphasis(qualifiedName, page, attributeMap);
327                 break;
328 
329             case HtmlExample.TAG_NAME:
330                 element = new HtmlExample(qualifiedName, page, attributeMap);
331                 break;
332 
333             case HtmlFieldSet.TAG_NAME:
334                 element = new HtmlFieldSet(qualifiedName, page, attributeMap);
335                 break;
336 
337             case HtmlFigure.TAG_NAME:
338                 element = new HtmlFigure(qualifiedName, page, attributeMap);
339                 break;
340 
341             case HtmlFigureCaption.TAG_NAME:
342                 element = new HtmlFigureCaption(qualifiedName, page, attributeMap);
343                 break;
344 
345             case HtmlFont.TAG_NAME:
346                 element = new HtmlFont(qualifiedName, page, attributeMap);
347                 break;
348 
349             case HtmlForm.TAG_NAME:
350                 element = new HtmlForm(qualifiedName, page, attributeMap);
351                 break;
352 
353             case HtmlFooter.TAG_NAME:
354                 element = new HtmlFooter(qualifiedName, page, attributeMap);
355                 break;
356 
357             case HtmlFrame.TAG_NAME:
358                 if (attributeMap != null) {
359                     final DomAttr srcAttribute = attributeMap.get("src");
360                     if (srcAttribute != null) {
361                         srcAttribute.setValue(srcAttribute.getValue().trim());
362                     }
363                 }
364                 element = new HtmlFrame(qualifiedName, page, attributeMap);
365                 break;
366 
367             case HtmlFrameSet.TAG_NAME:
368                 element = new HtmlFrameSet(qualifiedName, page, attributeMap);
369                 break;
370 
371             case HtmlHead.TAG_NAME:
372                 element = new HtmlHead(qualifiedName, page, attributeMap);
373                 break;
374 
375             case HtmlHeader.TAG_NAME:
376                 element = new HtmlHeader(qualifiedName, page, attributeMap);
377                 break;
378 
379             case HtmlHeading1.TAG_NAME:
380                 element = new HtmlHeading1(qualifiedName, page, attributeMap);
381                 break;
382 
383             case HtmlHeading2.TAG_NAME:
384                 element = new HtmlHeading2(qualifiedName, page, attributeMap);
385                 break;
386 
387             case HtmlHeading3.TAG_NAME:
388                 element = new HtmlHeading3(qualifiedName, page, attributeMap);
389                 break;
390 
391             case HtmlHeading4.TAG_NAME:
392                 element = new HtmlHeading4(qualifiedName, page, attributeMap);
393                 break;
394 
395             case HtmlHeading5.TAG_NAME:
396                 element = new HtmlHeading5(qualifiedName, page, attributeMap);
397                 break;
398 
399             case HtmlHeading6.TAG_NAME:
400                 element = new HtmlHeading6(qualifiedName, page, attributeMap);
401                 break;
402 
403             case HtmlHorizontalRule.TAG_NAME:
404                 element = new HtmlHorizontalRule(qualifiedName, page, attributeMap);
405                 break;
406 
407             case HtmlHtml.TAG_NAME:
408                 element = new HtmlHtml(qualifiedName, page, attributeMap);
409                 break;
410 
411             case HtmlImage.TAG_NAME:
412             case HtmlImage.TAG_NAME2:
413                 element = new HtmlImage(qualifiedName, page, attributeMap);
414                 break;
415 
416             case HtmlInlineFrame.TAG_NAME:
417                 if (attributeMap != null) {
418                     final DomAttr srcAttribute = attributeMap.get("src");
419                     if (srcAttribute != null) {
420                         srcAttribute.setValue(srcAttribute.getValue().trim());
421                     }
422                 }
423                 element = new HtmlInlineFrame(qualifiedName, page, attributeMap);
424                 break;
425 
426             case HtmlInlineQuotation.TAG_NAME:
427                 element = new HtmlInlineQuotation(qualifiedName, page, attributeMap);
428                 break;
429 
430             case HtmlInsertedText.TAG_NAME:
431                 element = new HtmlInsertedText(qualifiedName, page, attributeMap);
432                 break;
433 
434             case HtmlIsIndex.TAG_NAME:
435                 element = new HtmlIsIndex(qualifiedName, page, attributeMap);
436                 break;
437 
438             case HtmlItalic.TAG_NAME:
439                 element = new HtmlItalic(qualifiedName, page, attributeMap);
440                 break;
441 
442             case HtmlKeyboard.TAG_NAME:
443                 element = new HtmlKeyboard(qualifiedName, page, attributeMap);
444                 break;
445 
446             case HtmlLabel.TAG_NAME:
447                 element = new HtmlLabel(qualifiedName, page, attributeMap);
448                 break;
449 
450             case HtmlLayer.TAG_NAME:
451                 element = new HtmlLayer(qualifiedName, page, attributeMap);
452                 break;
453 
454             case HtmlLegend.TAG_NAME:
455                 element = new HtmlLegend(qualifiedName, page, attributeMap);
456                 break;
457 
458             case HtmlLink.TAG_NAME:
459                 element = new HtmlLink(qualifiedName, page, attributeMap);
460                 break;
461 
462             case HtmlListing.TAG_NAME:
463                 element = new HtmlListing(qualifiedName, page, attributeMap);
464                 break;
465 
466             case HtmlListItem.TAG_NAME:
467                 element = new HtmlListItem(qualifiedName, page, attributeMap);
468                 break;
469 
470             case HtmlMain.TAG_NAME:
471                 element = new HtmlMain(qualifiedName, page, attributeMap);
472                 break;
473 
474             case HtmlMap.TAG_NAME:
475                 element = new HtmlMap(qualifiedName, page, attributeMap);
476                 break;
477 
478             case HtmlMark.TAG_NAME:
479                 element = new HtmlMark(qualifiedName, page, attributeMap);
480                 break;
481 
482             case HtmlMarquee.TAG_NAME:
483                 element = new HtmlMarquee(qualifiedName, page, attributeMap);
484                 break;
485 
486             case HtmlMenu.TAG_NAME:
487                 element = new HtmlMenu(qualifiedName, page, attributeMap);
488                 break;
489 
490             case HtmlMenuItem.TAG_NAME:
491                 element = new HtmlMenuItem(qualifiedName, page, attributeMap);
492                 break;
493 
494             case HtmlMeta.TAG_NAME:
495                 element = new HtmlMeta(qualifiedName, page, attributeMap);
496                 break;
497 
498             case HtmlMeter.TAG_NAME:
499                 element = new HtmlMeter(qualifiedName, page, attributeMap);
500                 break;
501 
502             case HtmlMultiColumn.TAG_NAME:
503                 element = new HtmlMultiColumn(qualifiedName, page, attributeMap);
504                 break;
505 
506             case HtmlNav.TAG_NAME:
507                 element = new HtmlNav(qualifiedName, page, attributeMap);
508                 break;
509 
510             case HtmlNextId.TAG_NAME:
511                 element = new HtmlNextId(qualifiedName, page, attributeMap);
512                 break;
513 
514             case HtmlNoBreak.TAG_NAME:
515                 element = new HtmlNoBreak(qualifiedName, page, attributeMap);
516                 break;
517 
518             case HtmlNoEmbed.TAG_NAME:
519                 element = new HtmlNoEmbed(qualifiedName, page, attributeMap);
520                 break;
521 
522             case HtmlNoFrames.TAG_NAME:
523                 element = new HtmlNoFrames(qualifiedName, page, attributeMap);
524                 break;
525 
526             case HtmlNoLayer.TAG_NAME:
527                 element = new HtmlNoLayer(qualifiedName, page, attributeMap);
528                 break;
529 
530             case HtmlNoScript.TAG_NAME:
531                 element = new HtmlNoScript(qualifiedName, page, attributeMap);
532                 break;
533 
534             case HtmlObject.TAG_NAME:
535                 element = new HtmlObject(qualifiedName, page, attributeMap);
536                 break;
537 
538             case HtmlOption.TAG_NAME:
539                 element = new HtmlOption(qualifiedName, page, attributeMap);
540                 break;
541 
542             case HtmlOptionGroup.TAG_NAME:
543                 element = new HtmlOptionGroup(qualifiedName, page, attributeMap);
544                 break;
545 
546             case HtmlOrderedList.TAG_NAME:
547                 element = new HtmlOrderedList(qualifiedName, page, attributeMap);
548                 break;
549 
550             case HtmlOutput.TAG_NAME:
551                 element = new HtmlOutput(qualifiedName, page, attributeMap);
552                 break;
553 
554             case HtmlParagraph.TAG_NAME:
555                 element = new HtmlParagraph(qualifiedName, page, attributeMap);
556                 break;
557 
558             case HtmlParameter.TAG_NAME:
559                 element = new HtmlParameter(qualifiedName, page, attributeMap);
560                 break;
561 
562             case HtmlPicture.TAG_NAME:
563                 element = new HtmlPicture(qualifiedName, page, attributeMap);
564                 break;
565 
566             case HtmlPlainText.TAG_NAME:
567                 element = new HtmlPlainText(qualifiedName, page, attributeMap);
568                 break;
569 
570             case HtmlPreformattedText.TAG_NAME:
571                 element = new HtmlPreformattedText(qualifiedName, page, attributeMap);
572                 break;
573 
574             case HtmlProgress.TAG_NAME:
575                 element = new HtmlProgress(qualifiedName, page, attributeMap);
576                 break;
577 
578             case HtmlRp.TAG_NAME:
579                 element = new HtmlRp(qualifiedName, page, attributeMap);
580                 break;
581 
582             case HtmlRt.TAG_NAME:
583                 element = new HtmlRt(qualifiedName, page, attributeMap);
584                 break;
585 
586             case HtmlRuby.TAG_NAME:
587                 element = new HtmlRuby(qualifiedName, page, attributeMap);
588                 break;
589 
590             case HtmlS.TAG_NAME:
591                 element = new HtmlS(qualifiedName, page, attributeMap);
592                 break;
593 
594             case HtmlSample.TAG_NAME:
595                 element = new HtmlSample(qualifiedName, page, attributeMap);
596                 break;
597 
598             case HtmlScript.TAG_NAME:
599                 element = new HtmlScript(qualifiedName, page, attributeMap);
600                 break;
601 
602             case HtmlSection.TAG_NAME:
603                 element = new HtmlSection(qualifiedName, page, attributeMap);
604                 break;
605 
606             case HtmlSelect.TAG_NAME:
607                 element = new HtmlSelect(qualifiedName, page, attributeMap);
608                 break;
609 
610             case HtmlSmall.TAG_NAME:
611                 element = new HtmlSmall(qualifiedName, page, attributeMap);
612                 break;
613 
614             case HtmlSlot.TAG_NAME:
615                 element = new HtmlSlot(qualifiedName, page, attributeMap);
616                 break;
617 
618             case HtmlSource.TAG_NAME:
619                 element = new HtmlSource(qualifiedName, page, attributeMap);
620                 break;
621 
622             case HtmlSpan.TAG_NAME:
623                 element = new HtmlSpan(qualifiedName, page, attributeMap);
624                 break;
625 
626             case HtmlStrike.TAG_NAME:
627                 element = new HtmlStrike(qualifiedName, page, attributeMap);
628                 break;
629 
630             case HtmlStrong.TAG_NAME:
631                 element = new HtmlStrong(qualifiedName, page, attributeMap);
632                 break;
633 
634             case HtmlStyle.TAG_NAME:
635                 element = new HtmlStyle(qualifiedName, page, attributeMap);
636                 break;
637 
638             case HtmlSubscript.TAG_NAME:
639                 element = new HtmlSubscript(qualifiedName, page, attributeMap);
640                 break;
641 
642             case HtmlSummary.TAG_NAME:
643                 element = new HtmlSummary(qualifiedName, page, attributeMap);
644                 break;
645 
646             case HtmlSuperscript.TAG_NAME:
647                 element = new HtmlSuperscript(qualifiedName, page, attributeMap);
648                 break;
649 
650             case HtmlSvg.TAG_NAME:
651                 element = new HtmlSvg(qualifiedName, page, attributeMap);
652                 break;
653 
654             case HtmlTable.TAG_NAME:
655                 element = new HtmlTable(qualifiedName, page, attributeMap);
656                 break;
657 
658             case HtmlTableBody.TAG_NAME:
659                 element = new HtmlTableBody(qualifiedName, page, attributeMap);
660                 break;
661 
662             case HtmlTableColumn.TAG_NAME:
663                 element = new HtmlTableColumn(qualifiedName, page, attributeMap);
664                 break;
665 
666             case HtmlTableColumnGroup.TAG_NAME:
667                 element = new HtmlTableColumnGroup(qualifiedName, page, attributeMap);
668                 break;
669 
670             case HtmlTableDataCell.TAG_NAME:
671                 element = new HtmlTableDataCell(qualifiedName, page, attributeMap);
672                 break;
673 
674             case HtmlTableFooter.TAG_NAME:
675                 element = new HtmlTableFooter(qualifiedName, page, attributeMap);
676                 break;
677 
678             case HtmlTableHeader.TAG_NAME:
679                 element = new HtmlTableHeader(qualifiedName, page, attributeMap);
680                 break;
681 
682             case HtmlTableHeaderCell.TAG_NAME:
683                 element = new HtmlTableHeaderCell(qualifiedName, page, attributeMap);
684                 break;
685 
686             case HtmlTableRow.TAG_NAME:
687                 element = new HtmlTableRow(qualifiedName, page, attributeMap);
688                 break;
689 
690             case HtmlTeletype.TAG_NAME:
691                 element = new HtmlTeletype(qualifiedName, page, attributeMap);
692                 break;
693 
694             case HtmlTemplate.TAG_NAME:
695                 element = new HtmlTemplate(qualifiedName, page, attributeMap);
696                 break;
697 
698             case HtmlTextArea.TAG_NAME:
699                 element = new HtmlTextArea(qualifiedName, page, attributeMap);
700                 break;
701 
702             case HtmlTime.TAG_NAME:
703                 element = new HtmlTime(qualifiedName, page, attributeMap);
704                 break;
705 
706             case HtmlTitle.TAG_NAME:
707                 element = new HtmlTitle(qualifiedName, page, attributeMap);
708                 break;
709 
710             case HtmlTrack.TAG_NAME:
711                 element = new HtmlTrack(qualifiedName, page, attributeMap);
712                 break;
713 
714             case HtmlUnderlined.TAG_NAME:
715                 element = new HtmlUnderlined(qualifiedName, page, attributeMap);
716                 break;
717 
718             case HtmlUnorderedList.TAG_NAME:
719                 element = new HtmlUnorderedList(qualifiedName, page, attributeMap);
720                 break;
721 
722             case HtmlVariable.TAG_NAME:
723                 element = new HtmlVariable(qualifiedName, page, attributeMap);
724                 break;
725 
726             case HtmlVideo.TAG_NAME:
727                 element = new HtmlVideo(qualifiedName, page, attributeMap);
728                 break;
729 
730             case HtmlWordBreak.TAG_NAME:
731                 element = new HtmlWordBreak(qualifiedName, page, attributeMap);
732                 break;
733 
734             default:
735                 throw new IllegalStateException("Cannot find HtmlElement for " + qualifiedName);
736         }
737 
738         final JavaScriptConfiguration config = page.getWebClient().getJavaScriptEngine().getJavaScriptConfiguration();
739         if (config != null && !"td".equals(tagName) && !"th".equals(tagName)
740                 && checkBrowserCompatibility && config.getDomJavaScriptMapping().get(element.getClass()) == null) {
741             return UnknownElementFactory.instance.createElementNS(page, namespaceURI, qualifiedName, attributes);
742         }
743         return element;
744     }
745 
746     /**
747      * Converts {@link Attributes} into the map needed by {@link HtmlElement}s.
748      *
749      * @param page the page which contains the specified attributes
750      * @param attributes the SAX attributes
751      * @return the map of attribute values for {@link HtmlElement}s
752      */
753     static Map<String, DomAttr> toMap(final SgmlPage page, final Attributes attributes) {
754         Map<String, DomAttr> attributeMap = null;
755         if (attributes != null) {
756             attributeMap = new LinkedHashMap<>(attributes.getLength());
757             for (int i = 0; i < attributes.getLength(); i++) {
758                 final String qName = attributes.getQName(i);
759                 // browsers consider only first attribute (ex: <div id='foo' id='something'>...</div>)
760                 if (!attributeMap.containsKey(qName)) {
761                     String namespaceURI = attributes.getURI(i);
762                     if (namespaceURI != null && namespaceURI.isEmpty()) {
763                         namespaceURI = null;
764                     }
765                     final DomAttr newAttr = new DomAttr(page, namespaceURI, qName, attributes.getValue(i), true);
766                     attributeMap.put(qName, newAttr);
767                 }
768             }
769         }
770         return attributeMap;
771     }
772 }