diff --git a/core/src/main/java/org/fao/geonet/kernel/EditLib.java b/core/src/main/java/org/fao/geonet/kernel/EditLib.java
index c08322ec61..ae70dcd5e6 100644
--- a/core/src/main/java/org/fao/geonet/kernel/EditLib.java
+++ b/core/src/main/java/org/fao/geonet/kernel/EditLib.java
@@ -50,6 +50,7 @@
import org.apache.commons.jxpath.ri.parser.Token;
import org.apache.commons.jxpath.ri.parser.XPathParser;
import org.apache.commons.jxpath.ri.parser.XPathParserConstants;
+import org.apache.commons.lang.StringUtils;
import org.fao.geonet.constants.Edit;
import org.fao.geonet.constants.Geonet;
import org.fao.geonet.domain.Pair;
@@ -583,7 +584,10 @@ public boolean addElementOrFragmentFromXpath(Element metadataRecord,
}
} else if (propNode instanceof Attribute) {
Element parent = ((Attribute) propNode).getParent();
- parent.removeAttribute(((Attribute) propNode).getName());
+ Attribute targetAttribute = (Attribute) propNode;
+ parent.removeAttribute(
+ targetAttribute.getName(),
+ targetAttribute.getNamespace());
}
} else {
// Update element content with node
@@ -736,6 +740,7 @@ private boolean createAndAddFromXPath(Element metadataRecord, MetadataSchema met
boolean isAttribute = false;
String currentElementName = "";
String currentElementNamespacePrefix = "";
+ String currentAttributeNamespacePrefix = "";
// Stop when token is null, start of an expression is found ie. "["
//
@@ -758,10 +763,15 @@ private boolean createAndAddFromXPath(Element metadataRecord, MetadataSchema met
isAttribute = true;
}
// Match namespace prefix
- if (currentToken.kind == XPathParserLocalConstants.TEXT && previousToken.kind == XPathParserConstants.SLASH) {
+ if (currentToken.kind == XPathParserLocalConstants.TEXT &&
+ previousToken.kind == XPathParserConstants.SLASH) {
// get element namespace if element is text and previous was /
// means qualified name only is supported
currentElementNamespacePrefix = currentToken.image;
+ } else if (isAttribute &&
+ previousToken.kind == XPathParserLocalConstants.TEXT &&
+ currentToken.kind == XPathParserLocalConstants.NAMESPACE_SEP) {
+ currentAttributeNamespacePrefix = previousToken.image;
} else if (currentToken.kind == XPathParserLocalConstants.TEXT &&
previousToken.kind == XPathParserLocalConstants.NAMESPACE_SEP) {
// get element name if element is text and previous was /
@@ -788,7 +798,9 @@ private boolean createAndAddFromXPath(Element metadataRecord, MetadataSchema met
} else {
LOGGER_ADD_ELEMENT.debug(" > add new node {} inserted in {}", qualifiedName, currentNode.getName());
- if (metadataSchema.getElementValues(qualifiedName, currentNode.getQualifiedName()) != null) {
+ if (isAttribute) {
+ existingElement = false; // Attribute is created and set after.
+ } else if (metadataSchema.getElementValues(qualifiedName, currentNode.getQualifiedName()) != null) {
currentNode = addElement(metadataSchema, currentNode, qualifiedName);
existingElement = false;
} else {
@@ -833,7 +845,15 @@ private boolean createAndAddFromXPath(Element metadataRecord, MetadataSchema met
doAddFragmentFromXpath(metadataSchema, value.getNodeValue(), currentNode);
} else {
if (isAttribute) {
- currentNode.setAttribute(previousToken.image, value.getStringValue());
+ if (StringUtils.isNotEmpty(currentAttributeNamespacePrefix)) {
+ currentNode.setAttribute(previousToken.image,
+ value.getStringValue(),
+ Namespace.getNamespace(currentAttributeNamespacePrefix,
+ metadataSchema.getNS(currentAttributeNamespacePrefix)));
+ } else {
+ currentNode.setAttribute(previousToken.image, value.getStringValue());
+ }
+
} else {
currentNode.setText(value.getStringValue());
}
diff --git a/services/src/test/java/org/fao/geonet/services/metadata/BatchEditsServiceTest.java b/services/src/test/java/org/fao/geonet/services/metadata/BatchEditsServiceTest.java
index 7c6ce23d64..08000955a7 100644
--- a/services/src/test/java/org/fao/geonet/services/metadata/BatchEditsServiceTest.java
+++ b/services/src/test/java/org/fao/geonet/services/metadata/BatchEditsServiceTest.java
@@ -39,6 +39,7 @@
import org.fao.geonet.domain.AbstractMetadata;
import org.fao.geonet.kernel.datamanager.IMetadataUtils;
import org.fao.geonet.kernel.mef.MEFLibIntegrationTest;
+import org.fao.geonet.schema.iso19115_3_2018.ISO19115_3_2018Namespaces;
import org.fao.geonet.services.AbstractServiceIntegrationTest;
import org.jdom.Attribute;
import org.jdom.Element;
@@ -322,6 +323,66 @@ public void testUpdateRecordAddAttribute() throws Exception {
Assert.assertEquals("value", ((Element) scope.get(0)).getAttributeValue("newAttribute"));
}
+ @Test
+ public void testUpdateRecordAddAndDeleteAttributeWithNamespace() throws Exception {
+ final String uuid = "db07463b-6769-401e-944b-f22e2e3bcc26";
+ BatchEditParameter[] listOfupdates = new BatchEditParameter[]{
+ new BatchEditParameter(
+ "/mdb:MD_Metadata/mdb:metadataScope/@gco:nilReason",
+ "withheld"
+ )
+ };
+
+ this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
+ this.mockHttpSession = loginAsAdmin();
+
+ Gson gson = new GsonBuilder()
+ .create();
+ JsonElement jsonEl = gson.toJsonTree(listOfupdates);
+
+ this.mockMvc.perform(put("/srv/api/records/batchediting?uuids=" + uuid)
+ .content(jsonEl.toString())
+ .contentType(MediaType.APPLICATION_JSON)
+ .session(this.mockHttpSession)
+ .accept(MediaType.parseMediaType("application/json")))
+ .andExpect(status().is(201));
+
+ AbstractMetadata updatedRecord = repository.findOneByUuid(uuid);
+ Element xml = Xml.loadString(updatedRecord.getData(), false);
+
+ List scope = org.fao.geonet.utils.Xml.selectNodes(xml,
+ "./mdb:metadataScope",
+ xml.getAdditionalNamespaces());
+ Assert.assertEquals("withheld", ((Element) scope.get(0)).getAttributeValue("nilReason", ISO19115_3_2018Namespaces.GCO));
+
+
+ listOfupdates = new BatchEditParameter[]{
+ new BatchEditParameter(
+ "/mdb:MD_Metadata/mdb:metadataScope/@gco:nilReason",
+ ""
+ )
+ };
+
+ jsonEl = gson.toJsonTree(listOfupdates);
+
+ this.mockMvc.perform(put("/srv/api/records/batchediting?uuids=" + uuid)
+ .content(jsonEl.toString())
+ .contentType(MediaType.APPLICATION_JSON)
+ .session(this.mockHttpSession)
+ .accept(MediaType.parseMediaType("application/json")))
+ .andExpect(status().is(201));
+
+ updatedRecord = repository.findOneByUuid(uuid);
+ xml = Xml.loadString(updatedRecord.getData(), false);
+
+ scope = org.fao.geonet.utils.Xml.selectNodes(xml,
+ "./mdb:metadataScope/gco:nilReason",
+ xml.getAdditionalNamespaces());
+ Assert.assertEquals(0, scope.size());
+
+ }
+
+
@Test
public void testUpdateRecordElement() throws Exception {
final String uuid = "db07463b-6769-401e-944b-f22e2e3bcc26";