-
Notifications
You must be signed in to change notification settings - Fork 551
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
EndnotesPart.AddHyperlinkRelationship not generating proper endnotes.xml.rels #1778
Comments
I believe you see this issue because if there are no using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using W = DocumentFormat.OpenXml.Wordprocessing;
string dir = @"C:\source\tmp\";
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
string docxPath = @$"{dir}bbb - Copy.docx";
var outputPath = $"{dir}{DateTime.Now.Ticks}.docx";
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"Processing file {Path.GetFileName(docxPath)}");
using (var memoryStream = File.Open(docxPath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
using (var destinationStream = File.Create(outputPath))
using (var document = WordprocessingDocument.Open(memoryStream, true))
{
Console.WriteLine($"Adding endnote having url");
MainDocumentPart mainDocumentPart = document.MainDocumentPart ?? document.AddMainDocumentPart();
EndnotesPart endNotesPart = mainDocumentPart.EndnotesPart ?? mainDocumentPart.AddNewPart<EndnotesPart>();
if (endNotesPart.Endnotes is null)
{
endNotesPart.Endnotes = new Endnotes();
}
long endNoteId = GenerateEndnoteWithHyperlink(endNotesPart);
mainDocumentPart.Document?.Body?.ChildElements.OfType<Paragraph>().LastOrDefault()?.InsertAfterSelf(GenerateParagraph(endNoteId));
memoryStream.Seek(0, SeekOrigin.Begin);
memoryStream.CopyTo(destinationStream);
}
try
{
using (var document = WordprocessingDocument.Open(outputPath, true))
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Could open generated document ({outputPath})");
Console.ForegroundColor = ConsoleColor.Yellow;
}
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"Could not open generated document ({outputPath}) due to error {ex.Message}");
Console.ForegroundColor = ConsoleColor.Yellow;
}
Console.WriteLine();
Console.WriteLine("Hit enter to exit");
Console.ReadLine();
Paragraph GenerateParagraph(long endnoteId)
{
Paragraph paragraph1 = new Paragraph();
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
ParagraphMarkRunProperties paragraphMarkRunProperties1 = new ParagraphMarkRunProperties();
Languages languages1 = new Languages() { Val = "en-IN" };
paragraphMarkRunProperties1.Append(languages1);
paragraphProperties1.Append(paragraphMarkRunProperties1);
W.Run run1 = new W.Run();
W.RunProperties runProperties1 = new W.RunProperties();
Languages languages2 = new Languages() { Val = "en-IN" };
runProperties1.Append(languages2);
W.Text text1 = new W.Text();
text1.Text = "Adding paragraph having endnote containing hyperlink.";
run1.Append(runProperties1);
run1.Append(text1);
W.Run run2 = new W.Run();
W.RunProperties runProperties2 = new W.RunProperties();
RunStyle runStyle1 = new RunStyle() { Val = "EndnoteReference" };
Languages languages3 = new Languages() { Val = "en-IN" };
runProperties2.Append(runStyle1);
runProperties2.Append(languages3);
EndnoteReference endnoteReference1 = new EndnoteReference() { Id = endnoteId };
run2.Append(runProperties2);
run2.Append(endnoteReference1);
paragraph1.Append(paragraphProperties1);
paragraph1.Append(run1);
paragraph1.Append(run2);
return paragraph1;
}
long GenerateEndnoteWithHyperlink(EndnotesPart endnotesPart)
{
long nextId = endnotesPart.Endnotes.ChildElements.OfType<Endnote>().Max(x => x.Id?.Value) + 1 ?? 1;
Endnote endnote1 = new Endnote() { Id = nextId };
Paragraph paragraph1 = new Paragraph();
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId() { Val = "EndnoteText" };
ParagraphMarkRunProperties paragraphMarkRunProperties1 = new ParagraphMarkRunProperties();
Languages languages1 = new Languages() { Val = "en-IN" };
paragraphMarkRunProperties1.Append(languages1);
paragraphProperties1.Append(paragraphStyleId1);
paragraphProperties1.Append(paragraphMarkRunProperties1);
W.Run run1 = new W.Run();
W.RunProperties runProperties1 = new W.RunProperties();
RunStyle runStyle1 = new RunStyle() { Val = "EndnoteReference" };
runProperties1.Append(runStyle1);
EndnoteReferenceMark endnoteReferenceMark1 = new EndnoteReferenceMark();
run1.Append(runProperties1);
run1.Append(endnoteReferenceMark1);
W.Run run2 = new W.Run();
W.Text text1 = new W.Text() { Space = SpaceProcessingModeValues.Preserve };
text1.Text = " ";
run2.Append(text1);
var relId = endnotesPart.AddHyperlinkRelationship(new Uri("https://www.dummyurlfromcode.com"), true).Id;
W.Hyperlink hyperlink1 = new W.Hyperlink() { History = true, Id = relId };
W.Run run3 = new W.Run() { RsidRunProperties = "005B5038" };
W.RunProperties runProperties2 = new W.RunProperties();
RunStyle runStyle2 = new RunStyle() { Val = "Hyperlink" };
Languages languages2 = new Languages() { Val = "en-IN" };
runProperties2.Append(runStyle2);
runProperties2.Append(languages2);
W.Text text2 = new W.Text();
text2.Text = "https://www.dummyurlfromcode.com";
run3.Append(runProperties2);
run3.Append(text2);
hyperlink1.Append(run3);
paragraph1.Append(paragraphProperties1);
paragraph1.Append(run1);
paragraph1.Append(run2);
paragraph1.Append(hyperlink1);
endnote1.Append(paragraph1);
endnotesPart.Endnotes.Append(endnote1);
return endnote1.Id?.Value ?? throw new InvalidOperationException("Failed to generate a valid endnote id");
} |
Hi @mikeebowen, Thank you for your response, but I would like to draw your attention to part where endnotes is already available in document and it also has 3 endnote. Check below for details. Here issue is that relationship part for XML is not getting generated by calling Endnote will get added but while opening the document it will fail as related hyperlink part is missing. Refer below screenshot of running shared console application. Let me know if I am missing something or in case you need more information. Also note that, I tried adding below shared code but it will not get executed as document already have endnotes node along with multiple endnote.
Thanks, |
@bhargavgaglani07, Can you share your code? It works for me to add an endnote to an existing endnotes. The null check is there in case the document does not already have endnotes. |
Hi @mikeebowen, Sure, please find attached console application, running the same will reproduce issue. Kindly note that here issue is not with adding endnote (no null reference exception is observed). Endnote gets added but when document is being opened at that time issue is observed due to missing reference part. Let me know if you need more information. Thanks |
@mikeebowen can you take a look at this again with the latest changes I've pushed in? |
Hi @bhargavgaglani07, your repro uses the OpenXML SDK 2.5.0, which is out of support. The sample I posted uses 3+. Please reformat your code to use 3+ and see if the issue persists. |
Hi @mikeebowen , It is reproducible with v3.1.1 as well. Please find attached sample console application. EndnotesWithURLIssue_v3.1.1.zip Thanks, |
There is an issue somewhere in your code. I refactored to use using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using W = DocumentFormat.OpenXml.Wordprocessing;
foreach (var path in Directory.GetFiles(@"C:\source\tmp\bar"))
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"Processing file {Path.GetFileName(path)}");
if (!Directory.Exists(@"C:\source\tmp\bar\foo"))
{
Directory.CreateDirectory(@"C:\source\tmp\bar\foo");
}
var outputPath = $@"C:\source\tmp\bar\foo\{DateTime.Now.Ticks}.docx";
var documentPayload = File.ReadAllBytes(path);
using (var memoryStream = new MemoryStream())
{
memoryStream.Position = 0;
memoryStream.Write(documentPayload);
using (var wordprocessingDocument = WordprocessingDocument.Open(memoryStream, true))
{
if (wordprocessingDocument?.MainDocumentPart?.EndnotesPart is not null && wordprocessingDocument?.MainDocumentPart?.Document?.Body is not null)
{
Console.WriteLine("Adding endnote with url");
var endNoteId = GenerateEndnoteWithHyperlink(wordprocessingDocument.MainDocumentPart.EndnotesPart);
wordprocessingDocument.MainDocumentPart.Document.Body.AppendChild(GenerateParagraph(endNoteId));
wordprocessingDocument.MainDocumentPart.EndnotesPart.Endnotes.Save();
wordprocessingDocument.MainDocumentPart.Document.Save();
wordprocessingDocument.Save();
File.WriteAllBytes(outputPath, memoryStream.ToArray());
}
}
}
try
{
using (var document = WordprocessingDocument.Open(outputPath, true))
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine($"Could open generated document ({outputPath})");
Console.ForegroundColor = ConsoleColor.Yellow;
}
}
catch (Exception ex)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"Could not open generated document ({outputPath}) due to error {ex.Message}");
Console.ForegroundColor = ConsoleColor.Yellow;
}
}
Paragraph GenerateParagraph(long endnoteId)
{
Paragraph paragraph1 = new Paragraph();
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
ParagraphMarkRunProperties paragraphMarkRunProperties1 = new ParagraphMarkRunProperties();
Languages languages1 = new Languages() { Val = "en-IN" };
paragraphMarkRunProperties1.Append(languages1);
paragraphProperties1.Append(paragraphMarkRunProperties1);
W.Run run1 = new W.Run();
W.RunProperties runProperties1 = new W.RunProperties();
Languages languages2 = new Languages() { Val = "en-IN" };
runProperties1.Append(languages2);
W.Text text1 = new W.Text();
text1.Text = "Adding paragraph having endnote containing hyperlink.";
run1.Append(runProperties1);
run1.Append(text1);
W.Run run2 = new W.Run();
W.RunProperties runProperties2 = new W.RunProperties();
RunStyle runStyle1 = new RunStyle() { Val = "EndnoteReference" };
Languages languages3 = new Languages() { Val = "en-IN" };
runProperties2.Append(runStyle1);
runProperties2.Append(languages3);
EndnoteReference endnoteReference1 = new EndnoteReference() { Id = endnoteId };
run2.Append(runProperties2);
run2.Append(endnoteReference1);
paragraph1.Append(paragraphProperties1);
paragraph1.Append(run1);
paragraph1.Append(run2);
return paragraph1;
}
long GenerateEndnoteWithHyperlink(EndnotesPart endnotesPart)
{
long nextId = endnotesPart.Endnotes.ChildElements.OfType<Endnote>().Max(x => x.Id?.Value) + 1 ?? 1;
Endnote endnote1 = new Endnote() { Id = nextId };
Paragraph paragraph1 = new Paragraph();
ParagraphProperties paragraphProperties1 = new ParagraphProperties();
ParagraphStyleId paragraphStyleId1 = new ParagraphStyleId() { Val = "EndnoteText" };
ParagraphMarkRunProperties paragraphMarkRunProperties1 = new ParagraphMarkRunProperties();
Languages languages1 = new Languages() { Val = "en-IN" };
paragraphMarkRunProperties1.Append(languages1);
paragraphProperties1.Append(paragraphStyleId1);
paragraphProperties1.Append(paragraphMarkRunProperties1);
W.Run run1 = new W.Run();
W.RunProperties runProperties1 = new W.RunProperties();
RunStyle runStyle1 = new RunStyle() { Val = "EndnoteReference" };
runProperties1.Append(runStyle1);
EndnoteReferenceMark endnoteReferenceMark1 = new EndnoteReferenceMark();
run1.Append(runProperties1);
run1.Append(endnoteReferenceMark1);
W.Run run2 = new W.Run();
W.Text text1 = new W.Text() { Space = SpaceProcessingModeValues.Preserve };
text1.Text = " ";
run2.Append(text1);
var relId = endnotesPart.AddHyperlinkRelationship(new Uri("https://www.dummyurlfromcode.com"), true).Id;
W.Hyperlink hyperlink1 = new W.Hyperlink() { History = true, Id = relId };
W.Run run3 = new W.Run() { RsidRunProperties = "005B5038" };
W.RunProperties runProperties2 = new W.RunProperties();
RunStyle runStyle2 = new RunStyle() { Val = "Hyperlink" };
Languages languages2 = new Languages() { Val = "en-IN" };
runProperties2.Append(runStyle2);
runProperties2.Append(languages2);
W.Text text2 = new W.Text();
text2.Text = "https://www.dummyurlfromcode.com";
run3.Append(runProperties2);
run3.Append(text2);
hyperlink1.Append(run3);
paragraph1.Append(paragraphProperties1);
paragraph1.Append(run1);
paragraph1.Append(run2);
paragraph1.Append(hyperlink1);
endnote1.Append(paragraph1);
endnotesPart.Endnotes.Append(endnote1);
return endnote1.Id?.Value ?? throw new InvalidOperationException("Failed to generate a valid endnote id");
} |
@bhargavgaglani07, the code from the post above works, but I was also able to make your code work by creating a new Console project and copy/pasting your code, only changing the file paths and it also adds the hyperlinks and relationships correctly. Can you test with different files? Maybe the .docx you're using is malformed somehow. Here is the working project EndnoteWithURL.zip |
Describe the bug
Adding an endnote having hyperlink into a document having no existing relationship for an endnote part is not generating proper endnotes.xml.rels file due to which generated document cannot be open using MS word or any other related application.
Screenshots
To Reproduce
Kindly run attached console app to reproduce the issue.
EndnotesWithURLIssue.zip
Observed behavior
If same code is executed (EndnotesPart.AddHyperlinkRelationship) for document already having an existing relationship present for endnotepart then generated document can be opened.
Expected behavior
EndnotesPart.AddHyperlinkRelationship should create a proper endnotes.xml.rels if not present.
Desktop (please complete the following information):
Debug Info
Adding below code before adding hyperlink relationship fixes the issue.
The text was updated successfully, but these errors were encountered: