diff --git a/src/BloomExe/Book/Book.cs b/src/BloomExe/Book/Book.cs index ba7886bb84bc..39fffde89671 100644 --- a/src/BloomExe/Book/Book.cs +++ b/src/BloomExe/Book/Book.cs @@ -1273,6 +1273,13 @@ private void FixDuplicateAudioIdsInDataDiv(HtmlDom bookDOM, HashSet idSe return; // shouldn't happen, but paranoia sometimes pays off, especially in running tests. var nodes = dataDiv .SafeSelectNodes("(.//div|.//span)[@id and contains(@class,'audio-sentence')]") + // We expect the customCover to have copies of other stuff in the data div. + .Where(x => + !( + x is SafeXmlElement e + && e.ParentWithAttributeValue("data-book", "customCover") != null + ) + ) .ToList(); var duplicateAudioIdsFixed = 0; foreach (var audioElement in nodes) diff --git a/src/BloomExe/SafeXml/SafeXmlElement.cs b/src/BloomExe/SafeXml/SafeXmlElement.cs index 90672a469354..ad19a032cc3e 100644 --- a/src/BloomExe/SafeXml/SafeXmlElement.cs +++ b/src/BloomExe/SafeXml/SafeXmlElement.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Xml; @@ -201,6 +201,30 @@ public SafeXmlElement ParentOrSelfWithClass(string targetClass) return current; } + public SafeXmlElement ParentWithAttribute(string targetAttribute) + { + var current = ParentElement; + while (current != null && !current.HasAttribute(targetAttribute)) + current = current.ParentNode as SafeXmlElement; + return current; + } + + /// + /// Get a parent element if any that has the specified value for the specified attribute + /// Note: currently if attrVal is empty it will match both parents where the attribute + /// is present and empty, and parents that don't have the attribute at all. It is not + /// intended that it should be used this way. + /// + public SafeXmlElement ParentWithAttributeValue(string targetAttribute, string attrVal) + { + ArgumentException.ThrowIfNullOrEmpty(attrVal); + + var current = ParentElement; + while (current != null && current.GetAttribute(targetAttribute) != attrVal) + current = current.ParentNode as SafeXmlElement; + return current; + } + public SafeXmlElement GetChildWithName(string name) { return ChildNodes.FirstOrDefault(n => n.Name.ToLowerInvariant() == name)