diff --git a/cdm/core/src/main/java/ucar/nc2/internal/ncml/NcmlReader.java b/cdm/core/src/main/java/ucar/nc2/internal/ncml/NcmlReader.java index df76a96854..cb55b68a26 100644 --- a/cdm/core/src/main/java/ucar/nc2/internal/ncml/NcmlReader.java +++ b/cdm/core/src/main/java/ucar/nc2/internal/ncml/NcmlReader.java @@ -288,7 +288,7 @@ public static NetcdfDataset.Builder mergeNcml(NetcdfFile ref, @Nullable Element if (ncmlElem != null) { NcmlReader reader = new NcmlReader(); - reader.readGroup(targetDS, null, null, ncmlElem); + reader.readGroup(targetDS, null, ref.getRootGroup(), ncmlElem); } setEnhanceMode(targetDS, ncmlElem, null); @@ -574,9 +574,12 @@ private Group.Builder readGroup(NetcdfDataset.Builder builder, @Nullable Group.B Group refGroup = null; if (parent == null) { - refGroup = this.refFile == null ? null : this.refFile.getRootGroup(); + if (this.refFile != null) { + refGroup = this.refFile.getRootGroup(); + } else if (refParent != null) { + refGroup = refParent; + } groupBuilder = builder.rootGroup; - } else { String name = groupElem.getAttributeValue("name"); if (name == null) { diff --git a/cdm/core/src/test/data/ncml/modifyNestedGroups.xml b/cdm/core/src/test/data/ncml/modifyNestedGroups.xml new file mode 100644 index 0000000000..5e23c2a646 --- /dev/null +++ b/cdm/core/src/test/data/ncml/modifyNestedGroups.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + diff --git a/cdm/core/src/test/data/testModifyNestedGroups.nc4 b/cdm/core/src/test/data/testModifyNestedGroups.nc4 new file mode 100644 index 0000000000..3685d9538b Binary files /dev/null and b/cdm/core/src/test/data/testModifyNestedGroups.nc4 differ diff --git a/cdm/core/src/test/java/ucar/nc2/internal/ncml/TestNcmlReader.java b/cdm/core/src/test/java/ucar/nc2/internal/ncml/TestNcmlReader.java index 00f307cacd..3509a10ff3 100644 --- a/cdm/core/src/test/java/ucar/nc2/internal/ncml/TestNcmlReader.java +++ b/cdm/core/src/test/java/ucar/nc2/internal/ncml/TestNcmlReader.java @@ -10,6 +10,8 @@ import org.jdom2.input.SAXBuilder; import org.junit.Test; import ucar.ma2.Array; +import ucar.nc2.Attribute; +import ucar.nc2.Group; import ucar.nc2.NetcdfFile; import ucar.nc2.Variable; import ucar.nc2.dataset.NetcdfDataset; @@ -25,8 +27,9 @@ public class TestNcmlReader { public void shouldMergeNcml() throws IOException, JDOMException { final String filename = TestDir.cdmLocalTestDataDir + "example1.nc"; - try (NetcdfFile netcdfFile = NetcdfDatasets.openFile(filename, null)) { - final NetcdfDataset netcdfDataset = NcmlReader.mergeNcml(netcdfFile, getNcmlElement("modifyVars.xml")).build(); + try (NetcdfFile netcdfFile = NetcdfDatasets.openFile(filename, null); + final NetcdfDataset netcdfDataset = + NcmlReader.mergeNcml(netcdfFile, getNcmlElement("modifyVars.xml")).build();) { final Variable ncmlVariable = netcdfDataset.findVariable("deltaLat"); assertThat((Object) ncmlVariable).isInstanceOf(VariableDS.class); @@ -40,9 +43,9 @@ public void shouldMergeNcml() throws IOException, JDOMException { public void shouldMergeNcmlWithEnhancements() throws IOException, JDOMException { final String filename = TestDir.cdmLocalTestDataDir + "example1.nc"; - try (NetcdfFile netcdfFile = NetcdfDatasets.openFile(filename, null)) { - final NetcdfDataset netcdfDataset = - NcmlReader.mergeNcml(netcdfFile, getNcmlElement("enhance/testStandardizer.ncml")).build(); + try (NetcdfFile netcdfFile = NetcdfDatasets.openFile(filename, null); + final NetcdfDataset netcdfDataset = + NcmlReader.mergeNcml(netcdfFile, getNcmlElement("enhance/testStandardizer.ncml")).build();) { final Variable ncmlVariable = netcdfDataset.findVariable("doublevar"); assertThat((Object) ncmlVariable).isNotNull(); @@ -51,6 +54,49 @@ public void shouldMergeNcmlWithEnhancements() throws IOException, JDOMException } } + @Test + public void mergeWithExistingGroups() throws IOException, JDOMException { + final String filename = TestDir.cdmLocalTestDataDir + "testModifyNestedGroups.nc4"; + + try (NetcdfFile netcdfFile = NetcdfDatasets.openFile(filename, null); + final NetcdfDataset netcdfDataset = + NcmlReader.mergeNcml(netcdfFile, getNcmlElement("modifyNestedGroups.xml")).build()) { + + final Group ncmlOuterGroup = netcdfDataset.findGroup("/outer_group"); + assertThat(ncmlOuterGroup).isNotNull(); + + final Attribute ncmlOuterAttribute = ncmlOuterGroup.findAttribute("new_outer_attr"); + assertThat(ncmlOuterAttribute).isNotNull(); + assertThat(ncmlOuterAttribute.getStringValue()).isNotNull(); + assertThat(ncmlOuterAttribute.getStringValue()).isEqualTo("new_outer_attr_value"); + + final Variable ncmlOuterVar = ncmlOuterGroup.findVariableLocal("lat"); + assertThat(ncmlOuterVar != null).isTrue(); + assertThat(ncmlOuterVar.attributes().hasAttribute("new_lat_attr")).isTrue(); + assertThat(ncmlOuterVar.attributes().findAttribute("new_lat_attr")).isNotNull(); + assertThat(ncmlOuterVar.attributes().findAttribute("new_lat_attr").getStringValue()).isNotNull(); + assertThat(ncmlOuterVar.attributes().findAttribute("new_lat_attr").getStringValue()) + .isEqualTo("new_lat_attr_value"); + // + + final Group ncmlInnerGroup = netcdfDataset.findGroup("/outer_group/inner_group"); + assertThat(ncmlInnerGroup).isNotNull(); + + final Attribute ncmlInnerAttribute = ncmlInnerGroup.findAttribute("new_inner_attr"); + assertThat(ncmlInnerAttribute).isNotNull(); + assertThat(ncmlInnerAttribute.getStringValue()).isNotNull(); + assertThat(ncmlInnerAttribute.getStringValue()).isEqualTo("new_inner_attr_value"); + + final Variable ncmlInnerVar = ncmlInnerGroup.findVariableLocal("lon"); + assertThat(ncmlInnerVar != null).isTrue(); + assertThat(ncmlInnerVar.attributes().hasAttribute("new_lon_attr")).isTrue(); + assertThat(ncmlInnerVar.attributes().findAttribute("new_lon_attr")).isNotNull(); + assertThat(ncmlInnerVar.attributes().findAttribute("new_lon_attr").getStringValue()).isNotNull(); + assertThat(ncmlInnerVar.attributes().findAttribute("new_lon_attr").getStringValue()) + .isEqualTo("new_lon_attr_value"); + } + } + private static Element getNcmlElement(String filename) throws IOException, JDOMException { final String ncml = TestNcmlRead.topDir + filename; diff --git a/cdm/core/src/test/java/ucar/nc2/ncml/TestNcmlReadersCompare.java b/cdm/core/src/test/java/ucar/nc2/ncml/TestNcmlReadersCompare.java index 307d6c135e..890b485ad9 100644 --- a/cdm/core/src/test/java/ucar/nc2/ncml/TestNcmlReadersCompare.java +++ b/cdm/core/src/test/java/ucar/nc2/ncml/TestNcmlReadersCompare.java @@ -78,6 +78,9 @@ public boolean accept(File pathname) { // NcMLReader does not change variable to type int, so fails. if (name.contains("aggSynthetic.xml")) return false; + // Simulates a TDS datasetScan using NcML and does not fully define a dataset. + if (name.contains("modifyNestedGroups.xml")) + return false; // Bug in old reader if (name.contains("testStandaloneNoEnhance.ncml")) return false;