How to Edit or replace the text or the hyperlinks of XPS File using System.Windows.XPS.Packaging?
Hello,
- Here I am trying to Update or edit the existing Text or Hyperlinks from XPS File. So I have seen a way using System.Windows.XPS.Packaging. By using this I have successfully read the content of the file but unable to write in it.
So kindly please suggest me further.
For you reference I am attaching the sample code below and the sample file.
I am not able to attached the xps or zip file so please take one sample file.
- There is any "XpsDetails" class in System.Windows.Xps.Packaging?
Code:
XpsDocument _xpsDocument=new XpsDocument("/path",System.IO.FileAccess.Read);
IXpsFixedDocumentSequenceReader fixedDocSeqReader
=_xpsDocument.FixedDocumentSequenceReader;
IXpsFixedDocumentReader _document = fixedDocSeqReader.FixedDocuments[0];
IXpsFixedPageReader _page
= _document.FixedPages[documentViewerElement.MasterPageNumber];
StringBuilder _currentText = new StringBuilder();
System.Xml.XmlReader _pageContentReader = _page.XmlReader;
if (_pageContentReader != null)
{
while (_pageContentReader.Read())
{
if (_pageContentReader.Name == "Glyphs")
{
if (_pageContentReader.HasAttributes)
{
if (_pageContentReader.GetAttribute("UnicodeString") != null )
{
_currentText.
Append(_pageContentReader.
GetAttribute("UnicodeString"));
}
}
}
}
}
string _fullPageText = _currentText.ToString();
Windows Presentation Foundation
Visual Studio
Microsoft System Center
-
Hui Liu-MSFT 38,251 Reputation points • Microsoft Vendor
2023-03-24T09:56:02.3133333+00:00 Hi,@Akbar Husain. Welcome Microsoft Q&A.
Could you show sample code that reproduces your problem? You can also try to see if the solution is helpful to you.
-
Akbar Husain 0 Reputation points
2023-03-24T12:45:44.8533333+00:00 Hello @Hui Liu-MSFT , thanks for the reply,
The solution you have mentioned that I found earlier but I want to replace the text and the hyperlinks from xps file and I not have any idea from where can I start. So if you have the code for it then it will be quite helpful to me.
-
Akbar Husain 0 Reputation points
2023-03-24T12:57:01.7933333+00:00 Below is the code that I have found but after replacing the file has crashed it is not opening?
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Documents; using System.Windows.Forms; using System.Windows.Xps.Packaging; using System.Windows.Xps.Serialization; using System.Xml; namespace AsposeXPS { public partial class Form3 : Form { string strDestXpsPath; string strSrcXpsPath; //List<XpsDetails> xpsImages = new List<XpsDetails>(); //List<XpsDetails> xpsFonts = new List<XpsDetails>(); public Form3() { InitializeComponent(); } private void Form3_Load(object sender, EventArgs e) { try { txtFilePath.Text = "Source File"; strDestXpsPath = "Destination File"; } catch (Exception ex) { } } { try { Aspose.Page.License objLicense = new Aspose.Page.License(); objLicense.SetLicense("Aspose.Total.NET.lic"); } catch (Exception ex) { } } public static class ImageType { public static string PNG = ".png"; public static string JPG = ".jpg"; public static string JPEG = ".jpeg"; public static string TIF = ".tif"; public static string TIFF = ".tiff"; public static string WDP = ".wdp"; } private void btnCreate_Click(object sender, EventArgs e) { try { strSrcXpsPath = txtFilePath.Text.Trim(); // Reading the string to replace. if (CreateNewXPSFromSource()) { MessageBox.Show("Edit Completed"); } } catch (Exception ex) { } } private bool CreateNewXPSFromSource() { bool blnResult = false; try { // Delete the old file generated by our code. if (File.Exists(strDestXpsPath)) File.Delete(strDestXpsPath); // Creating the output XPS file. XpsDocument document = new XpsDocument(strDestXpsPath, FileAccess.ReadWrite, System.IO.Packaging.CompressionOption.Maximum); IXpsFixedDocumentSequenceWriter docSeqWriter = document.AddFixedDocumentSequence(); // Loading the source xps files to list to read them for edit. List<string> sourceFiles = new List<string>(); sourceFiles.Add(strSrcXpsPath); // Looping each source files. foreach (string sourceFile in sourceFiles) { XpsDocument docToRead = new XpsDocument(sourceFile, FileAccess.ReadWrite); IXpsFixedDocumentSequenceReader docSequenceToRead = docToRead.FixedDocumentSequenceReader; foreach (IXpsFixedDocumentReader fixedDocumentReader in docSequenceToRead.FixedDocuments) { IXpsFixedDocumentWriter fixedDocumentWriter = docSeqWriter.AddFixedDocument(); AddStructure(fixedDocumentReader, fixedDocumentWriter); foreach (IXpsFixedPageReader fixedPageReader in fixedDocumentReader.FixedPages) { IXpsFixedPageWriter pageWriter = fixedDocumentWriter.AddFixedPage(); AddImages(fixedPageReader, pageWriter); AddFonts(fixedPageReader, pageWriter); AddContent(fixedPageReader, pageWriter); // Commmit all changes. pageWriter.Commit(); } fixedDocumentWriter.Commit(); } // Close the current source before openeing next one. docToRead.Close(); } docSeqWriter.Commit(); // Show the modified content in a DocumentViewer. //dvModifiedXPS.Document = document.GetFixedDocumentSequence(); //ModifiedGrid.Visibility = System.Windows.Visibility.Visible; // Close newly created XPS document. document.Close(); blnResult = true; } catch (Exception ex) { MessageBox.Show(ex.Message); } return blnResult; } private static void AddStructure(IXpsFixedDocumentReader fixedDocumentReader, IXpsFixedDocumentWriter fixedDocumentWriter) { XpsStructure Structure = fixedDocumentReader.DocumentStructure; if (Structure != null) { XpsStructure myStructure = fixedDocumentWriter.AddDocumentStructure(); using (Stream destStream = myStructure.GetStream()) { using (Stream sourceStream = Structure.GetStream()) { CopyStream(sourceStream, destStream); myStructure.Commit(); } } } } private static Int32 CopyStream(Stream sourceStream, Stream destStream) { const int size = 64 * 1024; byte[] localBuffer = new byte[size]; int bytesRead; Int32 bytesMoved = 0; sourceStream.Seek(0, SeekOrigin.Begin); destStream.Seek(0, SeekOrigin.Begin); while ((bytesRead = sourceStream.Read(localBuffer, 0, size)) > 0) { destStream.Write(localBuffer, 0, bytesRead); bytesMoved += bytesRead; } return bytesMoved; } private void AddImages(IXpsFixedPageReader fixedPageReader, IXpsFixedPageWriter pageWriter) { // Adding images to resources. foreach (XpsImage image in fixedPageReader.Images) { XpsImage newImage = null; // Getting the URI to check the image extension. string sourceExt = image.Uri.ToString().ToLower(); if (sourceExt.Contains(ImageType.PNG)) { newImage = pageWriter.AddImage(XpsImageType.PngImageType); } else if (sourceExt.Contains(ImageType.JPG) || sourceExt.Contains(ImageType.JPEG)) { newImage = pageWriter.AddImage(XpsImageType.JpegImageType); } else if (sourceExt.Contains(ImageType.TIF) || sourceExt.Contains(ImageType.TIFF)) { newImage = pageWriter.AddImage(XpsImageType.TiffImageType); } else if (sourceExt.Contains(ImageType.WDP)) { newImage = pageWriter.AddImage(XpsImageType.WdpImageType); } else { newImage = null; } if (null != newImage) { using (Stream dstImageStream = newImage.GetStream()) { using (Stream srcImageStream = image.GetStream()) { CopyStream(srcImageStream, dstImageStream); newImage.Commit(); //XpsDetails xpsImage = new XpsDetails(); //xpsImage.resource = newImage; //xpsImage.sourceURI = image.Uri; //xpsImage.destURI = newImage.Uri; //xpsImages.Add(xpsImage); } } } } } private void AddFonts(IXpsFixedPageReader fixedPageReader, IXpsFixedPageWriter pageWriter) { // Adding font from source to resources. foreach (XpsFont font in fixedPageReader.Fonts) { if (!CheckIfFontAddedAlready(font.Uri.ToString())) { XpsFont newFont = pageWriter.AddFont(false); using (Stream dstFontStream = newFont.GetStream()) { using (Stream srcFontStream = font.GetStream()) { if (font.IsObfuscated) { WriteObfuscatedStream(font.Uri.ToString(), dstFontStream, srcFontStream); } else { WriteToStream(dstFontStream, srcFontStream); } newFont.Commit(); //XpsDetails xpsFont = new XpsDetails(); //xpsFont.resource = newFont; //xpsFont.sourceURI = font.Uri; //xpsFont.destURI = newFont.Uri; //xpsFonts.Add(xpsFont); } } } } } private void AddContent(IXpsFixedPageReader fixedPageReader, IXpsFixedPageWriter pageWriter) { XmlDocument xmlDoc = new XmlDocument(); // Loading XPS content. xmlDoc.Load(fixedPageReader.XmlReader); // Find and replace text to edit the XPS. EditXPSContent(xmlDoc.ChildNodes); // Writing the modified XML content to a new XPS doc. xmlDoc.Save(pageWriter.XmlWriter); } private void EditXPSContent(XmlNodeList childNodes) { int maxvalue = childNodes.Count; for (int i = 0; i < maxvalue; i++) { XmlNode node = childNodes[i]; if (node.HasChildNodes) { EditXPSContent(node.ChildNodes); } if (node.NodeType == XmlNodeType.Element) { if (node.Name == "Glyphs") { foreach (XmlAttribute attribute in node.Attributes) { if (attribute.Name == "UnicodeString") { //Compare String and replace. if (attribute.Value.Contains("For XPS File")) { node.Attributes["UnicodeString"].Value = node.Attributes["UnicodeString"].Value.Replace( "For XPS File", "For XPS File New."); //= newStringToReplace; node.Attributes["Indices"].Value = ""; } } if (attribute.Name == "FontUri") { node.Attributes["FontUri"].Value = GetNewFontUri( attribute.Value); } } } else if (node.Name == "ImageBrush") { foreach (XmlAttribute attribute in node.Attributes) { if (attribute.Name == "ImageSource") { // Get the uri of image added to resource. attribute.Value = GetNewImageUri(attribute.Value); } } } } } } private string GetNewFontUri(string oldUri) { string result = string.Empty; //foreach (XpsDetails data in xpsFonts) //{ // if (data.sourceURI.ToString() == oldUri.ToString()) // { // result = data.destURI.ToString(); // } //} return result; } private string GetNewImageUri(string oldUri) { string result = string.Empty; //foreach (XpsDetails data in xpsImages) //{ // if (data.sourceURI.ToString() == oldUri.ToString()) // { // result = data.destURI.ToString(); // } //} return result; } private bool CheckIfFontAddedAlready(string uri) { bool IsFontAdded = false; //foreach (XpsDetails data in xpsFonts) //{ // if (data.sourceURI.ToString() == uri) // { // IsFontAdded = true; // } //} return IsFontAdded; } private void WriteObfuscatedStream(string resourceName, Stream destStream, Stream sourceStream) { int bufSize = 0x1000; int guidByteSize = 16; int obfuscatedByte = 32; // Get the GUID byte from the resource name. Typical Font name: // /Resources/Fonts/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.ODTTF int startPos = resourceName.LastIndexOf('/') + 1; int length = resourceName.LastIndexOf('.') - startPos; resourceName = resourceName.Substring(startPos, length); Guid guid = new Guid(resourceName); string guidString = guid.ToString("N"); // Parsing the guid string and coverted into byte value byte[] guidBytes = new byte[guidByteSize]; for (int i = 0; i < guidBytes.Length; i++) { guidBytes[i] = Convert.ToByte(guidString.Substring(i * 2, 2), 16); } // XOR the first 32 bytes of the source // resource stream with GUID byte. byte[] buf = new byte[obfuscatedByte]; sourceStream.Read(buf, 0, obfuscatedByte); for (int i = 0; i < obfuscatedByte; i++) { int guidBytesPos = guidBytes.Length - (i % guidBytes.Length) - 1; buf[i] ^= guidBytes[guidBytesPos]; } destStream.Write(buf, 0, obfuscatedByte); // copy remaining stream from source without obfuscation buf = new byte[bufSize]; int bytesRead = 0; while ((bytesRead = sourceStream.Read(buf, 0, bufSize)) > 0) { destStream.Write(buf, 0, bytesRead); } //} } private void WriteToStream(Stream destStream, Stream sourceStream) { const int bufSize = 0x1000; byte[] buf = new byte[bufSize]; int bytesRead = 0; while ((bytesRead = sourceStream.Read(buf, 0, bufSize)) > 0) { destStream.Write(buf, 0, bytesRead); } } } }
-
Akbar Husain 0 Reputation points
2023-03-27T04:26:18.5266667+00:00 Hello,
I just want to add one more thing that there is any "XpsDetails" Class in System.Windows.XPS.Packaging?
Thanks in Advance
-
Hui Liu-MSFT 38,251 Reputation points • Microsoft Vendor
2023-03-30T09:27:04.94+00:00 Hi,@Akbar Husain .I tested your code and i executed the resulting Edit Completed. Could you share the steps for reproducing your problem? What is your expected concrete?
-
Akbar Husain 0 Reputation points
2023-03-30T10:38:39.9733333+00:00 Wow, How it is possible.
Can you please confirm that you have not changed anything in the code?
And the source file from which you have edited the content and the new destination file is opening successfully with the updated content.
If yes then can you please confirm that you have not updated the above code?
What about XpsDetails class? you have take the reference or you have remain the commented code for XpsDetails as it is?
-
Hui Liu-MSFT 38,251 Reputation points • Microsoft Vendor
2023-03-31T02:01:28.0733333+00:00 Hi,@Akbar Husain .
First of all, I'm not sure if the xps file changed successfully.
I'm not sure about the steps and expected results for reproducing your problem.
Could you explain the expected and actual results after the program is executed?
Here's how I did it.
I downloaded the xps file from the Internet. I created the Windows Forms project and copied your code.
The code you show has an extra
Try... Catch
block of code. It causes an error, so I commented it out.Then I add text boxes and buttons to match the event.
Try to execute the program, and just show the
Edit Completed
.private void Form3_Load(object sender, EventArgs e) { try { txtFilePath.Text = "Source File"; strDestXpsPath = "Destination File"; } catch (Exception ex) { } } { try { Aspose.Page.License objLicense = new Aspose.Page.License(); objLicense.SetLicense("Aspose.Total.NET.lic"); } catch (Exception ex) { } }
Sign in to comment