The sample validation hook used in this tutorial:
checks that the src
attribute of the img
element is not an absolute file path;
checks that the value of the name
attribute of a a
element is not already in use;
checks that for each href
attribute of a a
element starting with '#
' (local reference), there is an element with such name
or id
.
This sample validation hook implements the documentChecked
method and not the checkingDocument
method. The following code compiles just fine because interface ValidateHook
contains default —dummy— implementations of both the checkingDocument
and documentChecked
methods.
Excerpts from CheckLinks.java
:
public class CheckLinks implements ValidateHook { private static final Name SRC = Name.get("src"); private static final Name NAME = Name.get("name"); private static final Name ID = Name.get("id"); private static final Name HREF = Name.get("href"); @Override public Diagnostic[] documentChecked(Document doc, boolean canceled, Diagnostic[] diagnostics) { if (canceled) { return diagnostics; } final ArrayList<DiagnosticImpl> warnings = new ArrayList<DiagnosticImpl>(); final ArrayList<Element> links = new ArrayList<Element>(); final HashMap<String,List<Element>> anchors = new HashMap<String,List<Element>>(); Traversal.traverse(doc.getRootElement(), new Traversal.HandlerBase() { public Object enterElement(Element element) { String localName = element.getLocalName(); String anchorName = null; if ("img".equals(localName)) { String src = element.getAttribute(SRC); if (src != null) { if (src.startsWith("file:/") || src.startsWith("/") || src.startsWith("\\\\") || (src.length() >= 3 && Character.isLetter(src.charAt(0)) && src.regionMatches(1, ":\\", 0, 2))) { warnings.add(new DiagnosticImpl( element, "src attribute looks like an absolute file path", Diagnostic.Severity.SEMANTIC_WARNING)); } } } else if ("a".equals(localName)) { String href = element.getAttribute(HREF); if (href != null) { if (href.startsWith("#")) { links.add(element); } } else { anchorName = element.getAttribute(NAME); if (anchorName != null) { List<Element> elements = anchors.get(anchorName); if (elements == null) { elements = new ArrayList<Element>(); anchors.put(anchorName, elements); } elements.add(element); } } } String id = element.getAttribute(ID); if (id != null && !id.equals(anchorName)) { List<Element> elements = anchors.get(id); if (elements == null) { elements = new ArrayList<Element>(); anchors.put(id, elements); } elements.add(element); } return null; } }); int count = links.size(); for (int i = 0; i < count; ++i) { Element element = links.get(i); String id = element.getAttribute(HREF).substring(1); if (!anchors.containsKey(id)) { warnings.add(new DiagnosticImpl( element, "reference to non-existent name or id '" + id + "'", Diagnostic.Severity.SEMANTIC_WARNING)); } } Iterator<Map.Entry<String,List<Element>>> iter = anchors.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<String,List<Element>> entry = iter.next(); String id = entry.getKey(); List<Element> elements = entry.getValue(); count = elements.size(); for (int i = 1; i < count; ++i) { warnings.add(new DiagnosticImpl( elements.get(i), "name or id '" + id + "' already defined", Diagnostic.Severity.SEMANTIC_WARNING)); } } int warningCount = warnings.size(); if (warningCount > 0) { int diagnosticCount = diagnostics.length; Diagnostic[] diagnostics2 = new Diagnostic[diagnosticCount + warningCount]; System.arraycopy(diagnostics, 0, diagnostics2, 0, diagnosticCount); for (int i = 0; i < warningCount; ++i) { diagnostics2[diagnosticCount+i] = warnings.get(i); } diagnostics = diagnostics2; } return diagnostics; } }
If the | |
| |
If the value of the | |
Elements | |
Elements | |
Elements having an Note that a | |
Elements contained in | |
Elements contained in | |
If semantic warnings have been found for the document, they are added to the list of |