why openxml block document if it has hyperlink
Home › Forums › Open-Xml-Sdk › why openxml block document if it has hyperlink
Tagged: c#, embededimages, openxml
This topic contains 2 replies, has 2 voices, and was last updated by Anonymous 4 years, 2 months ago.
-
AuthorPosts
-
July 3, 2020 at 12:28 pm #8786
why openxml block document if it has hyperlink, how to resolve this issue
Thanks in advanced
PrasadJuly 30, 2020 at 6:51 am #8830Resolved !!!
i got following code from
Following is the complete listing of the class UriFixer, as well as the code to use it. The approach that you take when using this class is to first attempt to open the document as usual, catching OpenXmlPackageException. If that exception is thrown, and if the text of that exception contains “Invalid Hyperlink”, then the code calls UriFixer.FixInvalidUri. After calling FixInvalidUri, the code then opens the fixed document (or spreadsheet / presentation) as usual.using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using DocumentFormat.OpenXml.Packaging; class Program { static void Main(string[] args) { var fileName = @"..\..\..\Test.docx"; var newFileName = @"..\..\..\Fixed.docx"; var newFileInfo = new FileInfo(newFileName); if (newFileInfo.Exists) newFileInfo.Delete(); File.Copy(fileName, newFileName); WordprocessingDocument wDoc; try { using (wDoc = WordprocessingDocument.Open(newFileName, true)) { ProcessDocument(wDoc); } } catch (OpenXmlPackageException e) { if (e.ToString().Contains("Invalid Hyperlink")) { using (FileStream fs = new FileStream(newFileName, FileMode.OpenOrCreate, FileAccess.ReadWrite)) { UriFixer.FixInvalidUri(fs, brokenUri => FixUri(brokenUri)); } using (wDoc = WordprocessingDocument.Open(newFileName, true)) { ProcessDocument(wDoc); } } } } private static Uri FixUri(string brokenUri) { return new Uri("http://broken-link/"); } private static void ProcessDocument(WordprocessingDocument wDoc) { var elementCount = wDoc.MainDocumentPart.Document.Descendants().Count(); Console.WriteLine(elementCount); } } public static class UriFixer { public static void FixInvalidUri(Stream fs, Func<string, Uri> invalidUriHandler) { XNamespace relNs = "http://schemas.openxmlformats.org/package/2006/relationships"; using (ZipArchive za = new ZipArchive(fs, ZipArchiveMode.Update)) { foreach (var entry in za.Entries.ToList()) { if (!entry.Name.EndsWith(".rels")) continue; bool replaceEntry = false; XDocument entryXDoc = null; using (var entryStream = entry.Open()) { try { entryXDoc = XDocument.Load(entryStream); if (entryXDoc.Root != null && entryXDoc.Root.Name.Namespace == relNs) { var urisToCheck = entryXDoc .Descendants(relNs + "Relationship") .Where(r => r.Attribute("TargetMode") != null && (string)r.Attribute("TargetMode") == "External"); foreach (var rel in urisToCheck) { var target = (string)rel.Attribute("Target"); if (target != null) { try { Uri uri = new Uri(target); } catch (UriFormatException) { Uri newUri = invalidUriHandler(target); rel.Attribute("Target").Value = newUri.ToString(); replaceEntry = true; } } } } } catch (XmlException) { continue; } } if (replaceEntry) { var fullName = entry.FullName; entry.Delete(); var newEntry = za.CreateEntry(fullName); using (StreamWriter writer = new StreamWriter(newEntry.Open())) using (XmlWriter xmlWriter = XmlWriter.Create(writer)) { entryXDoc.WriteTo(xmlWriter); } } } } } }
We are considering including this method in the Open XML SDK itself. We would make a few overloads of the WordprocessingDocument.Open method, the SpreadsheetDocument.Open method, and the PresentationDocument.Open method. These overloads would take the callback as an argument, just as in the above example. These new methods would first attempt to open the document in the normal way. If the attempt to open is successful, then these methods would return the newly opened document. However, if System.IO.Packaging throws the OpenXmlPackageException, and if the document were opened for writing, then the method would open, modify, and save a fixed document. It would then attempt to open again, and return the newly opened document.
With this approach, the idiom to open the document would be almost identical to the current approach to opening a document. The only difference would be the inclusion of the callback method as an argument.
If the document was opened for read-only access, then the various methods would create a copy of the document in memory, fix the broken Uri objects, and then open and return the fixed document (for read-only access).
Please feel free to comment about how this approach would work for you. If we have agreement on this approach, then in a month or two, we will make the change to the open source version of the Open XML SDK.
October 9, 2020 at 11:14 am #9763
AnonymousYou can insert a Lock (<w:lock>) element in the SdtProperties-element – that will make the content read-only. For example this defines a plain text content control containing the text ‘hello’ which appears read-only when editing the document in Word:
<w:document>
<w:body>
<w:sdt>
<w:sdtPr>
<w:lock w:val=”contentLocked” />
<w:text />
</w:sdtPr>
<w:sdtContent>
<w:p>
<w:r>
<w:t>hello</w:t>
</w:r>
</w:p>
</w:sdtContent>
</w:sdt>
…
</w:body>
</w:document>
In code you can use something like this to add the lock:using (var document = WordprocessingDocument.Open(@”c:\temp\test.docx”, true))
{
SdtBlock sdtBlock =
document
.MainDocumentPart
.Document
.Body
.Descendants<SdtBlock>()
.Where(b => b.SdtProperties.GetFirstChild<Tag>().Val == “myTagName”)
.SingleOrDefault();var contentLock = new Lock { Val = LockingValues.SdtContentLocked };
sdtBlock.SdtProperties.AppendChild(contentLock);
}
I find it usefull to start with a Word-document and then use OpenXML Productivity Tool to see the xml produced by Word. -
AuthorPosts
You must be logged in to reply to this topic.