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 89b0aecf..79801373 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
@@ -116,7 +116,6 @@ class XmlContentHandler implements ContentHandler {
}
for (int i = 0; i < matchingNodes.getLength(); i++) {
Node node = matchingNodes.item(i);
-
if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
Attr attr = (Attr) node;
attr.getOwnerElement().removeAttributeNode(attr);
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 72048301..ad6653d3 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,22 +192,78 @@ 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())
+ public void xmlAttribute() throws IOException {
+ this.snippet.expectResponseFields("xml-attribute").withContents(
+ tableWithHeader("Path", "Type", "Description").row("a", "b", "one").row(
+ "a/@id", "c", "two"));
+ new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")
+ .type("b"), fieldWithPath("a/@id").description("two").type("c")))
+ .document(new OperationBuilder("xml-attribute", this.snippet
+ .getOutputDirectory())
.response()
- .content("5")
+ .content("foo")
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
.build());
}
+ @Test
+ public void missingXmlAttribute() throws IOException {
+ this.thrown.expect(SnippetException.class);
+ this.thrown
+ .expectMessage(equalTo("Fields with the following paths were not found"
+ + " in the payload: [a/@id]"));
+ new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")
+ .type("b"), fieldWithPath("a/@id").description("two").type("c")))
+ .document(new OperationBuilder("missing-xml-attribute", this.snippet
+ .getOutputDirectory())
+ .response()
+ .content("foo")
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
+ .build());
+ }
+
+ @Test
+ public void missingOptionalXmlAttribute() throws IOException {
+ this.snippet.expectResponseFields("missing-optional-xml-attribute").withContents(
+ tableWithHeader("Path", "Type", "Description").row("a", "b", "one").row(
+ "a/@id", "c", "two"));
+ new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")
+ .type("b"), fieldWithPath("a/@id").description("two").type("c")
+ .optional())).document(new OperationBuilder(
+ "missing-optional-xml-attribute", this.snippet.getOutputDirectory())
+ .response().content("foo")
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
+ .build());
+ }
+
+ @Test
+ public void undocumentedAttributeDoesNotCauseFailure() throws IOException {
+ this.snippet.expectResponseFields("undocumented-attribute").withContents(
+ tableWithHeader("Path", "Type", "Description").row("a", "a", "one"));
+ new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a").description("one")
+ .type("a"))).document(new OperationBuilder("undocumented-attribute",
+ this.snippet.getOutputDirectory()).response()
+ .content("bar")
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
+ .build());
+ }
+
+ @Test
+ public void documentedXmlAttributesAreRemoved() throws IOException {
+ this.thrown.expect(SnippetException.class);
+ this.thrown.expectMessage(equalTo(String
+ .format("The following parts of the payload were not documented:"
+ + "%nbar%n")));
+ new ResponseFieldsSnippet(Arrays.asList(fieldWithPath("a/@id").description("one")
+ .type("a"))).document(new OperationBuilder(
+ "documented-attribute-is-removed", this.snippet.getOutputDirectory())
+ .response().content("bar")
+ .header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML_VALUE)
+ .build());
+ }
+
@Test
public void xmlResponseFieldWithNoType() throws IOException {
this.thrown.expect(FieldTypeRequiredException.class);