diff --git a/styled-xml-parser/src/main/java/com/itextpdf/styledxmlparser/css/selector/item/CssAttributeSelectorItem.java b/styled-xml-parser/src/main/java/com/itextpdf/styledxmlparser/css/selector/item/CssAttributeSelectorItem.java index 0ff50ad089..97fb7fe9fc 100644 --- a/styled-xml-parser/src/main/java/com/itextpdf/styledxmlparser/css/selector/item/CssAttributeSelectorItem.java +++ b/styled-xml-parser/src/main/java/com/itextpdf/styledxmlparser/css/selector/item/CssAttributeSelectorItem.java @@ -103,7 +103,9 @@ public boolean matches(INode node) { case '$': return value.length() > 0 && attributeValue.endsWith(value); case '~': - String pattern = MessageFormatUtil.format("(^{0}\\s+)|(\\s+{1}\\s+)|(\\s+{2}$)", value, value, value); + String quotedValue = Pattern.quote(value); + String pattern = MessageFormatUtil.format("(^{0}\\s+)|(\\s+{1}\\s+)|(\\s+{2}$)", quotedValue, + quotedValue, quotedValue); return Pattern.compile(pattern).matcher(attributeValue).matches(); case '*': return value.length() > 0 && attributeValue.contains(value); diff --git a/styled-xml-parser/src/test/java/com/itextpdf/styledxmlparser/css/selector/item/CssMatchesTest.java b/styled-xml-parser/src/test/java/com/itextpdf/styledxmlparser/css/selector/item/CssMatchesTest.java index e0ff9ddbe2..bd504916c3 100644 --- a/styled-xml-parser/src/test/java/com/itextpdf/styledxmlparser/css/selector/item/CssMatchesTest.java +++ b/styled-xml-parser/src/test/java/com/itextpdf/styledxmlparser/css/selector/item/CssMatchesTest.java @@ -430,6 +430,48 @@ public void matchesRootSelectorItemTestNotTaggedText() { Assertions.assertFalse(item.matches(divNode)); } + @Test + public void matchesAttributeContainsWordTreatsValueAsLiteralTest() { + CssAttributeSelectorItem item = new CssAttributeSelectorItem("[data-info~=\"a.c\"]"); + IXmlParser htmlParser = new JsoupHtmlParser(); + IDocumentNode documentNode = htmlParser.parse("
"); + + INode bodyNode = documentNode + .childNodes().get(0) + .childNodes().get(1); + INode divNode = bodyNode.childNodes().get(0); + + Assertions.assertFalse(item.matches(divNode)); + } + + @Test + public void matchesAttributeContainsWordLiteralValueTest() { + CssAttributeSelectorItem item = new CssAttributeSelectorItem("[data-info~=\"abc\"]"); + IXmlParser htmlParser = new JsoupHtmlParser(); + IDocumentNode documentNode = htmlParser.parse(""); + + INode bodyNode = documentNode + .childNodes().get(0) + .childNodes().get(1); + INode divNode = bodyNode.childNodes().get(0); + + Assertions.assertTrue(item.matches(divNode)); + } + + @Test + public void matchesAttributeContainsWordInvalidRegexValueTest() { + CssAttributeSelectorItem item = new CssAttributeSelectorItem("[data-info~=\"(\"]"); + IXmlParser htmlParser = new JsoupHtmlParser(); + IDocumentNode documentNode = htmlParser.parse(""); + + INode bodyNode = documentNode + .childNodes().get(0) + .childNodes().get(1); + INode divNode = bodyNode.childNodes().get(0); + + Assertions.assertFalse(item.matches(divNode)); + } + @Test public void cssPageTypeSelectorItemMatchesTest() { CssPageTypeSelectorItem item = new CssPageTypeSelectorItem("customPageName");