diff --git a/include/rexsapi/XMLModelLoader.hxx b/include/rexsapi/XMLModelLoader.hxx index b4e0b1f..cba2d29 100644 --- a/include/rexsapi/XMLModelLoader.hxx +++ b/include/rexsapi/XMLModelLoader.hxx @@ -145,9 +145,15 @@ namespace rexsapi components = postProcessor.release(); TRelations relations; + std::set> usedRelations; for (const auto& relation : doc.select_nodes("/model/relations/relation")) { std::string relationId = detail::getStringAttribute(relation, "id"); try { + if (!usedRelations.emplace(relationId).second) { + result.addError( + TError{m_Mode.adapt(TErrorLevel::ERR), fmt::format("duplicate relation found for relation id={}", relationId)}); + } + auto relationType = relationTypeFromString(detail::getStringAttribute(relation, "type")); std::optional order; if (const auto orderAtt = relation.node().attribute("order"); !orderAtt.empty()) { @@ -159,8 +165,7 @@ namespace rexsapi } TRelationReferences references; - for (const auto& reference : - doc.select_nodes(fmt::format("/model/relations/relation[@id = '{}']/ref", relationId).c_str())) { + for (const auto& reference : relation.node().children("ref")) { std::string referenceId = detail::getStringAttribute(reference, "id"); try { auto role = relationRoleFromString(detail::getStringAttribute(reference, "role")); diff --git a/test/XMLModelLoaderTest.cxx b/test/XMLModelLoaderTest.cxx index 3dc87f5..0badaaf 100644 --- a/test/XMLModelLoaderTest.cxx +++ b/test/XMLModelLoaderTest.cxx @@ -398,6 +398,39 @@ TEST_CASE("XML model loader test") CHECK(model); } + SUBCASE("Load duplicate relation ids") + { + const std::string buffer = R"( + + + + + + + + + + + + + + + + + + + )"; + + rexsapi::detail::TBufferModelLoader loader{validator, + buffer}; + const auto model = loader.load(rexsapi::TMode::STRICT_MODE, result, registry); + CHECK_FALSE(result); + CHECK_FALSE(result.isCritical()); + REQUIRE(model); + REQUIRE(result.getErrors().size() == 1); + CHECK(result.getErrors()[0].getMessage() == "duplicate relation found for relation id=1"); + } + SUBCASE("Load invalid reference type") { const std::string buffer = R"(