I am having trouble updating a Hyperlink in a Word doc (Q How to update the body and a hyperlink in a Word doc ) and am zooming in on the Descendants<T>()
call not working. Here is my code:
using DocumentFormat.OpenXml.Packaging; //from NuGet ClosedXML
using DocumentFormat.OpenXml.Wordprocessing; //from NuGet ClosedXML
WordprocessingDocument doc = WordprocessingDocument.Open(...filename..., true);
MainDocumentPart mainPart = doc.MainDocumentPart;
IEnumerable<Hyperlink> hLinks = mainPart.Document.Body.Descendants<Hyperlink>();
The doc is opened OK because mainPart
gets a value. But hLinks
has no elements. If I open the Word doc in Word, a hyperlink is present and working.
In the Immediate Window I see the following values:
mainPart.Document.Body
-->
{DocumentFormat.OpenXml.Wordprocessing.Body}
ChildElements: {DocumentFormat.OpenXml.OpenXmlChildElements}
ExtendedAttributes: {DocumentFormat.OpenXml.EmptyEnumerable<DocumentFormat.OpenXml.OpenXmlAttribute>}
FirstChild: {DocumentFormat.OpenXml.OpenXmlUnknownElement}
HasAttributes: false
HasChildren: true
InnerText: "
lots of data, e.g:
...<w:t>100</w:t>...
mainPart.Document.Body.Descendants<Text>().First()
-->
Exception: "Sequence contains no elements"
If I cannot even find the text parts, how should I ever find and replace the hyperlink?
If you are sure there are elements in your file that you are searching with linq, and nothing is returning or you are getting exceptions, that typically points to a namespace problem.
If you post your entire file, I can better help you, but check to see if you can alias your namespace like so:
using W = DocumentFormat.OpenXml.Wordprocessing;
and then in your Descendants
call you do something like this:
var hLinks = mainPart.Document.Body.Descendants<W.Hyperlink>();
This answer demonstrates another namespace trick to try also.
Something seems to be wrong with my Word doc; it was generated with a tool. Testing with another Word doc, created with Word, gives better results. I am working on it ...
With a regular Word doc, looking at
doc.MainDocumentPart.Document.Body.InnerXml
the value starts with:
<w:p w:rsidR=\"00455325\" w:rsidRDefault=\"00341915\"
xmlns:w=\"http://schemas.openxmlformats.org/wordprocessingml/2006/main\">
<w:r>
<w:t>Hello World!
but with the word doc I am testing with, which comes from a tool I myself made:
<w:body xmlns:w=\"http://schemas.openxmlforma...
This explains a lot.
I will have to fix my tool :-)
Update:
The fix was that this did not give the correct part of data to insert in the Word Doc:
string strDocumentXml = newWordContent.DocumentElement.InnerXml;
but instead this is the correct data:
string strDocumentXml = newWordContent.DocumentElement.FirstChild.OuterXml;
Inspection with the debugger of:
doc.MainDocumentPart.Document.Body.InnerXml
as mentioned above, confirmed it. The Descendants call now returns the expected data, and updating the hyperlink works.
Side note:
I clearly fixed a bug in my app, but, apart from updating the hyperlink, the app worked perfectly OK before, with that bug :-)