From 58b992d99eaf277da7671e53c0a7fd3a65bd9534 Mon Sep 17 00:00:00 2001 From: cschaetzlein Date: Mon, 16 Nov 2015 16:15:04 +0100 Subject: [PATCH] Allow individual attributes in an XML element to be documented Documenting an XML attribute in the XML payload leads to a NullPointerException since no parent nodes exists for an XML attribute. Rather than always trying to remove a node from its parent, this commit changes the logic to apply special treament to nodes that are attributes and remove the attribute from its owning element instead. Closes gh-167 --- .../restdocs/payload/XmlContentHandler.java | 11 ++++++++++- .../payload/ResponseFieldsSnippetTests.java | 15 +++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java index a971f049..89b0aecf 100644 --- a/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java +++ b/spring-restdocs-core/src/main/java/org/springframework/restdocs/payload/XmlContentHandler.java @@ -34,6 +34,7 @@ import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; +import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; @@ -115,7 +116,15 @@ class XmlContentHandler implements ContentHandler { } for (int i = 0; i < matchingNodes.getLength(); i++) { Node node = matchingNodes.item(i); - node.getParentNode().removeChild(node); + + if (node.getNodeType() == Node.ATTRIBUTE_NODE) { + Attr attr = (Attr) node; + attr.getOwnerElement().removeAttributeNode(attr); + } + else { + node.getParentNode().removeChild(node); + } + } } if (payload.getChildNodes().getLength() > 0) { diff --git a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java index 337e6e8c..72048301 100644 --- a/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java +++ b/spring-restdocs-core/src/test/java/org/springframework/restdocs/payload/ResponseFieldsSnippetTests.java @@ -192,6 +192,21 @@ public class ResponseFieldsSnippetTests { .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE) .build()); } + + @Test + public void undocumentedXmlWithAttributeResponseField() throws IOException { + this.thrown.expect(SnippetException.class); + this.thrown + .expectMessage(equalTo("The following parts of the payload were not" + + " documented:\r\n\r\n 5\r\n\r\n")); + new ResponseFieldsSnippet(Arrays.asList(new FieldDescriptor("/a/b/@id").type("").description(""))) + .document(new OperationBuilder("undocumented-xml-response-field", + this.snippet.getOutputDirectory()) + .response() + .content("5") + .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE) + .build()); + } @Test public void xmlResponseFieldWithNoType() throws IOException {