Skip to content

Commit 279bcec

Browse files
krystiankaluznyKrystian Kałużny
authored andcommitted
Add extractingAttribute to map node to it's attribute value
1 parent fa180eb commit 279bcec

File tree

4 files changed

+101
-31
lines changed

4 files changed

+101
-31
lines changed

xmlunit-assertj/src/main/java/org/xmlunit/assertj/MultipleNodeAssert.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@
1515

1616
import static org.xmlunit.assertj.error.ShouldAnyNodeHaveXPath.shouldAnyNodeHaveXPath;
1717

18+
import java.util.ArrayList;
19+
import java.util.List;
1820
import java.util.Map;
1921

2022
import javax.xml.parsers.DocumentBuilderFactory;
2123
import javax.xml.transform.Source;
2224
import javax.xml.xpath.XPathFactory;
2325

26+
import org.assertj.core.api.AbstractListAssert;
2427
import org.assertj.core.api.FactoryBasedNavigableIterableAssert;
28+
import org.assertj.core.api.ObjectAssert;
29+
import org.assertj.core.description.Description;
2530
import org.w3c.dom.Node;
2631
import org.xmlunit.builder.Input;
2732
import org.xmlunit.util.Convert;
@@ -200,7 +205,6 @@ public MultipleNodeAssert containsAnyNodeHavingXPath(String xPath) {
200205
* @since XMLUnit 2.6.4
201206
*/
202207
public MultipleNodeAssert containsAllNodesHavingXPath(final String xPath) {
203-
204208
isNotNull();
205209

206210
allSatisfy(new SingleNodeAssertConsumer() {
@@ -213,6 +217,28 @@ public void accept(SingleNodeAssert singleNodeAssert) {
213217
return this;
214218
}
215219

220+
/**
221+
* Extracting values of given node's attribute.
222+
* If a node doesn't have the attribute then {@code null} value is return.
223+
*
224+
* @throws AssertionError if the actual nodes iterable is {@code null}.
225+
* @since XMLUnit 2.6.4
226+
*/
227+
public AbstractListAssert<?, List<? extends String>, String, ObjectAssert<String>> extractingAttribute(String attribute) {
228+
isNotNull();
229+
230+
List<String> values = new ArrayList<>();
231+
232+
for (Node node : actual) {
233+
values.add(NodeUtils.attributeValue(node, attribute));
234+
}
235+
236+
String extractedDescription = String.format("Extracted attribute: %s", attribute);
237+
String description = Description.mostRelevantDescription(this.info.description(), extractedDescription);
238+
239+
return newListAssertInstance(values).as(description);
240+
}
241+
216242
private void allSatisfy(SingleNodeAssertConsumer consumer) {
217243
int index = 0;
218244
for (Node node : actual) {
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/*
2+
This file is licensed to You under the Apache License, Version 2.0
3+
(the "License"); you may not use this file except in compliance with
4+
the License. You may obtain a copy of the License at
5+
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
8+
Unless required by applicable law or agreed to in writing, software
9+
distributed under the License is distributed on an "AS IS" BASIS,
10+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
See the License for the specific language governing permissions and
12+
limitations under the License.
13+
*/
14+
package org.xmlunit.assertj;
15+
16+
import java.util.Map;
17+
18+
import javax.xml.namespace.QName;
19+
20+
import org.w3c.dom.Node;
21+
import org.xmlunit.util.Nodes;
22+
23+
class NodeUtils {
24+
25+
private NodeUtils() {
26+
}
27+
28+
static String attributeValue(Node node, String attributeName) {
29+
30+
Map<QName, String> attributes = Nodes.getAttributes(node);
31+
32+
for (Map.Entry<QName, String> entry : attributes.entrySet()) {
33+
final QName qName = entry.getKey();
34+
if (matchQName(qName, attributeName)) {
35+
return entry.getValue();
36+
}
37+
}
38+
39+
return null;
40+
}
41+
42+
private static boolean matchQName(QName qName, String name) {
43+
44+
return qName.toString().equals(name)
45+
|| (qName.getPrefix() + ":" + qName.getLocalPart()).equals(name)
46+
|| qName.getLocalPart().equals(name);
47+
}
48+
}

xmlunit-assertj/src/main/java/org/xmlunit/assertj/SingleNodeAssert.java

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525

2626
import org.assertj.core.api.AbstractAssert;
2727
import org.w3c.dom.Node;
28-
import org.xmlunit.util.Nodes;
2928
import org.xmlunit.xpath.JAXPXPathEngine;
3029

3130
/**
@@ -61,8 +60,8 @@ public class SingleNodeAssert extends AbstractAssert<SingleNodeAssert, Node> {
6160
public SingleNodeAssert hasAttribute(String attributeName) {
6261
isNotNull();
6362

64-
final Map.Entry<QName, String> entry = attributeForName(attributeName);
65-
if (entry == null) {
63+
final String value = NodeUtils.attributeValue(actual, attributeName);
64+
if (value == null) {
6665
throwAssertionError(shouldHaveAttribute(actual.getNodeName(), attributeName));
6766
}
6867
return this;
@@ -77,8 +76,8 @@ public SingleNodeAssert hasAttribute(String attributeName) {
7776
public SingleNodeAssert hasAttribute(String attributeName, String attributeValue) {
7877
isNotNull();
7978

80-
final Map.Entry<QName, String> attribute = attributeForName(attributeName);
81-
if (attribute == null || !attribute.getValue().equals(attributeValue)) {
79+
final String value = NodeUtils.attributeValue(actual, attributeName);
80+
if (value == null || !value.equals(attributeValue)) {
8281
throwAssertionError(shouldHaveAttributeWithValue(actual.getNodeName(), attributeName, attributeValue));
8382
}
8483

@@ -94,8 +93,8 @@ public SingleNodeAssert hasAttribute(String attributeName, String attributeValue
9493
public SingleNodeAssert doesNotHaveAttribute(String attributeName) {
9594
isNotNull();
9695

97-
final Map.Entry<QName, String> entry = attributeForName(attributeName);
98-
if (entry != null) {
96+
final String value = NodeUtils.attributeValue(actual, attributeName);
97+
if (value != null) {
9998
throwAssertionError(shouldNotHaveAttribute(actual.getNodeName(), attributeName));
10099
}
101100
return this;
@@ -110,8 +109,8 @@ public SingleNodeAssert doesNotHaveAttribute(String attributeName) {
110109
public SingleNodeAssert doesNotHaveAttribute(String attributeName, String attributeValue) {
111110
isNotNull();
112111

113-
final Map.Entry<QName, String> attribute = attributeForName(attributeName);
114-
if (attribute != null && attribute.getValue().equals(attributeValue)) {
112+
final String value = NodeUtils.attributeValue(actual, attributeName);
113+
if (value != null && value.equals(attributeValue)) {
115114
throwAssertionError(shouldNotHaveAttributeWithValue(actual.getNodeName(), attributeName, attributeValue));
116115
}
117116

@@ -140,25 +139,4 @@ public SingleNodeAssert hasXPath(String xPath) {
140139
boolean isNodeSetEmpty(String xPath) {
141140
return !engine.selectNodes(xPath, actual).iterator().hasNext();
142141
}
143-
144-
private Map.Entry<QName, String> attributeForName(String attributeName) {
145-
146-
Map<QName, String> attributes = Nodes.getAttributes(actual);
147-
148-
for (Map.Entry<QName, String> entry : attributes.entrySet()) {
149-
final QName qName = entry.getKey();
150-
if (matchQName(qName, attributeName)) {
151-
return entry;
152-
}
153-
}
154-
155-
return null;
156-
}
157-
158-
private static boolean matchQName(QName qName, String name) {
159-
160-
return qName.toString().equals(name)
161-
|| (qName.getPrefix() + ":" + qName.getLocalPart()).equals(name)
162-
|| qName.getLocalPart().equals(name);
163-
}
164142
}

xmlunit-assertj/src/test/java/org/xmlunit/assertj/MultipleNodeAssertTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,4 +97,22 @@ public void testContainsAllNodesHavingXPath_shouldFailed() {
9797
.hasXPath("/feed/entry")
9898
.containsAllNodesHavingXPath("./title");
9999
}
100+
101+
@Test
102+
public void testExtractingAttribute_shouldPass() {
103+
104+
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
105+
"<feed>" +
106+
" <title>title</title>" +
107+
" <entry attr1=\"value1\" />" +
108+
" <entry attr1=\"value2\"/>" +
109+
" <entry />" +
110+
" <entry attr1=\"value4\" />" +
111+
"</feed>";
112+
113+
assertThat(xml)
114+
.nodesByXPath("/feed/entry")
115+
.extractingAttribute("attr1")
116+
.containsExactly("value1", "value2", null, "value4");
117+
}
100118
}

0 commit comments

Comments
 (0)