From 4dd89160dd5ced925bbc525aa23cb1f60a36e108 Mon Sep 17 00:00:00 2001 From: Grahame Grieve Date: Tue, 8 Sep 2020 12:45:13 +1000 Subject: [PATCH] Add validation for html block elements inside paragraphs --- .../r5/test/NarrativeGenerationTests.java | 2 +- .../fhir/utilities/i18n/I18nConstants.java | 1 + .../src/main/resources/Messages.properties | 3 ++- .../instance/InstanceValidator.java | 19 +++++++++++-------- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java index 9011cd929..6bb55c3ff 100644 --- a/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java +++ b/org.hl7.fhir.r5/src/test/java/org/hl7/fhir/r5/test/NarrativeGenerationTests.java @@ -152,7 +152,7 @@ public class NarrativeGenerationTests { x = RendererFactory.factory(source, rc).render(new ElementWrappers.ResourceWrapperMetaElement(rc, e)); target = TextFile.streamToString(TestingUtilities.loadTestResourceStream("r5", "narrative", test.getId() + "-meta.html")); - output = HEADER+new XhtmlComposer(true).compose(x)+FOOTER; + output = HEADER+new XhtmlComposer(true, true).compose(x)+FOOTER; TextFile.stringToFile(output, TestingUtilities.tempFile("narrative", test.getId() + "-meta.output.html")); Assertions.assertTrue(output.equals(target), "Output does not match expected (meta)"); } diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java index 93dd445ad..99f9fe519 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java @@ -579,6 +579,7 @@ public class I18nConstants { public static final String XHTML_XHTML_ATTRIBUTE_ILLEGAL = "XHTML_XHTML_Attribute_Illegal"; public static final String XHTML_XHTML_DOCTYPE_ILLEGAL = "XHTML_XHTML_DOCTYPE_ILLEGAL"; public static final String XHTML_XHTML_ELEMENT_ILLEGAL = "XHTML_XHTML_Element_Illegal"; + public static final String XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA = "XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA"; public static final String XHTML_XHTML_NAME_INVALID = "XHTML_XHTML_Name_Invalid"; public static final String XHTML_XHTML_NS_INVALID = "XHTML_XHTML_NS_InValid"; public static final String XML_ATTR_VALUE_INVALID = "xml_attr_value_invalid"; diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index c4705c191..bde0e0936 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -605,4 +605,5 @@ FHIRPATH_NUMERICAL_ONLY = Error evaluating FHIRPath expression: The function {0} FHIRPATH_DECIMAL_ONLY = Error evaluating FHIRPath expression: The function {0} can only be used on a decimal but found {1} FHIRPATH_FOCUS_PLURAL = Error evaluating FHIRPath expression: focus for {0} has more than one value REFERENCE_REF_SUSPICIOUS = The syntax of the reference ''{0}'' looks incorrect, and it should be checked -TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS = UCUM Codes that contain human readable annotations like {0} can be misleading. Best Practice is not to use annotations in the UCUM code, and rather to make sure that Quantity.unit is correctly human readable \ No newline at end of file +TYPE_SPECIFIC_CHECKS_DT_QTY_NO_ANNOTATIONS = UCUM Codes that contain human readable annotations like {0} can be misleading. Best Practice is not to use annotations in the UCUM code, and rather to make sure that Quantity.unit is correctly human readable +XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA = Illegal element name inside in a paragraph in the XHTML (''{0}'') diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java index 60ef546e1..465e0835b 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java @@ -2070,7 +2070,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat checkInnerNS(errors, e, path, xhtml.getChildNodes()); rule(errors, IssueType.INVALID, e.line(), e.col(), path, "div".equals(xhtml.getName()), I18nConstants.XHTML_XHTML_NAME_INVALID, ns); // check that no illegal elements and attributes have been used - checkInnerNames(errors, e, path, xhtml.getChildNodes()); + checkInnerNames(errors, e, path, xhtml.getChildNodes(), false); checkUrls(errors, e, path, xhtml.getChildNodes()); } } @@ -2171,7 +2171,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat "http://hl7.org/fhirpath/System.Decimal", "http://hl7.org/fhirpath/System.Date", "http://hl7.org/fhirpath/System.Time", "http://hl7.org/fhirpath/System.DateTime", "http://hl7.org/fhirpath/System.Quantity"); } - private void checkInnerNames(List errors, Element e, String path, List list) { + private void checkInnerNames(List errors, Element e, String path, List list, boolean inPara) { for (XhtmlNode node : list) { if (node.getNodeType() == NodeType.Comment) { rule(errors, IssueType.INVALID, e.line(), e.col(), path, !node.getContent().startsWith("DOCTYPE"), I18nConstants.XHTML_XHTML_DOCTYPE_ILLEGAL); @@ -2181,9 +2181,8 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat "p", "br", "div", "h1", "h2", "h3", "h4", "h5", "h6", "a", "span", "b", "em", "i", "strong", "small", "big", "tt", "small", "dfn", "q", "var", "abbr", "acronym", "cite", "blockquote", "hr", "address", "bdo", "kbd", "q", "sub", "sup", "ul", "ol", "li", "dl", "dt", "dd", "pre", "table", "caption", "colgroup", "col", "thead", "tr", "tfoot", "tbody", "th", "td", - "code", "samp", "img", "map", "area" - - ), I18nConstants.XHTML_XHTML_ELEMENT_ILLEGAL, node.getName()); + "code", "samp", "img", "map", "area"), I18nConstants.XHTML_XHTML_ELEMENT_ILLEGAL, node.getName()); + for (String an : node.getAttributes().keySet()) { boolean ok = an.startsWith("xmlns") || Utilities.existsInList(an, "title", "style", "class", ID, "lang", "xml:lang", "dir", "accesskey", "tabindex", @@ -2195,11 +2194,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat "img.alt", "img.longdesc", "img.height", "img.width", "img.usemap", "img.ismap", "map.name", "area.shape", "area.coords", "area.href", "area.nohref", "area.alt", "table.summary", "table.width", "table.border", "table.frame", "table.rules", "table.cellspacing", "table.cellpadding", "pre.space", "td.nowrap" - ); - if (!ok) + ); + if (!ok) { rule(errors, IssueType.INVALID, e.line(), e.col(), path, false, I18nConstants.XHTML_XHTML_ATTRIBUTE_ILLEGAL, an, node.getName()); + } } - checkInnerNames(errors, e, path, node.getChildNodes()); + + rule(errors, IssueType.INVALID, e.line(), e.col(), path, !(inPara && Utilities.existsInList(node.getName(), "div", "blockquote", "table", "ol", "ul", "p")) , I18nConstants.XHTML_XHTML_ELEMENT_ILLEGAL_IN_PARA, node.getName()); + + checkInnerNames(errors, e, path, node.getChildNodes(), inPara || "p".equals(node.getName())); } } }