diff --git a/src/DocumentFormat.OpenXml.Framework/OpenXmlElement.cs b/src/DocumentFormat.OpenXml.Framework/OpenXmlElement.cs
index 969db9c0d..9031b05de 100644
--- a/src/DocumentFormat.OpenXml.Framework/OpenXmlElement.cs
+++ b/src/DocumentFormat.OpenXml.Framework/OpenXmlElement.cs
@@ -796,11 +796,30 @@ public void RemoveNamespaceDeclaration(string prefix)
/// Finds the first child element in type T.
///
/// Type of element.
- ///
+ /// The first child element of type T or null
public T? GetFirstChild()
where T : OpenXmlElement
=> ChildElements.First();
+ ///
+ /// Finds the first child element of or adds a new element if it does not exist.
+ ///
+ /// Type of element.
+ /// The new or existing OpenXmlElement
+ public T GetOrAddFirstChild()
+ where T : OpenXmlElement, new()
+ {
+ var child = GetFirstChild();
+
+ if (child is null)
+ {
+ child = new T();
+ AppendChild(child);
+ }
+
+ return child;
+ }
+
///
/// Gets the OpenXmlElement element that immediately precedes the current OpenXmlElement element.
/// Returns null (Nothing in Visual Basic ) if there is no preceding OpenXmlElement element.
diff --git a/src/DocumentFormat.OpenXml.Framework/PublicAPI/PublicAPI.Shipped.txt b/src/DocumentFormat.OpenXml.Framework/PublicAPI/PublicAPI.Shipped.txt
index 8785a8f7f..c57cccff9 100644
--- a/src/DocumentFormat.OpenXml.Framework/PublicAPI/PublicAPI.Shipped.txt
+++ b/src/DocumentFormat.OpenXml.Framework/PublicAPI/PublicAPI.Shipped.txt
@@ -270,6 +270,7 @@ DocumentFormat.OpenXml.OpenXmlElement.Features.get -> DocumentFormat.OpenXml.Fea
DocumentFormat.OpenXml.OpenXmlElement.GetAttribute(string! localName, string! namespaceUri) -> DocumentFormat.OpenXml.OpenXmlAttribute
DocumentFormat.OpenXml.OpenXmlElement.GetAttributes() -> System.Collections.Generic.IList!
DocumentFormat.OpenXml.OpenXmlElement.GetFirstChild() -> T?
+DocumentFormat.OpenXml.OpenXmlElement.GetOrAddFirstChild() -> T!
DocumentFormat.OpenXml.OpenXmlElement.HasAttributes.get -> bool
DocumentFormat.OpenXml.OpenXmlElement.InsertAfterSelf(T! newElement) -> T!
DocumentFormat.OpenXml.OpenXmlElement.InsertBeforeSelf(T! newElement) -> T!
diff --git a/test/DocumentFormat.OpenXml.Tests/ofapiTest/OpenXmlElementTest2.cs b/test/DocumentFormat.OpenXml.Tests/ofapiTest/OpenXmlElementTest2.cs
index aab185f0d..98cd4fe18 100644
--- a/test/DocumentFormat.OpenXml.Tests/ofapiTest/OpenXmlElementTest2.cs
+++ b/test/DocumentFormat.OpenXml.Tests/ofapiTest/OpenXmlElementTest2.cs
@@ -216,5 +216,20 @@ internal override void ConfigureMetadata(ElementMetadata.Builder builder)
private class ChildElement : OpenXmlLeafElement
{
}
+
+ ///
+ /// A test for OpenXmlElement.GetOrAddFirstChild.
+ ///
+ [Fact]
+ public void GetOrAddFirstChildTest()
+ {
+ Paragraph p = new();
+ Run r = p.GetOrAddFirstChild();
+ Assert.NotNull(r);
+ Assert.Same(r, p.GetFirstChild());
+
+ var r2 = p.GetOrAddFirstChild();
+ Assert.Same(r, r2);
+ }
}
}