How to remove whitespace from XElement object created from XElement.ReadFrom(XmlReader) - whitespace

I am parsing a large xml file. So I am using an XmlReader in combination with XElement instead of XElement.Load().
I have created as XElement object from XmlReader as shown below and here.
static IEnumerable<XElement> StreamRootChildDoc(string uri)
{
using (XmlReader reader = XmlReader.Create(uri, xmlReaderSettings))
{
reader.MoveToContent();
// Parse the file and display each of the nodes.
while (reader.Read())
{
switch (reader.NodeType)
{
case XmlNodeType.Element:
if (reader.Name == "Child")
{
XElement el = XElement.ReadFrom(reader) as XElement;
if (el != null)
yield return el;
}
break;
}
}
}
}
I want to save this XElement object content in the database as string without the whitespace. None of the below 3 ways work. Just a note, if I load the xml in memory using XElement.Load(), the ToString(SaveOptions.DisableFormatting) works.
<root> <child></child> </root> //xml saved in db with whitespace
<root><child></child></root> //want to save as this
XElement.ToString(SaveOptions.DisableFormatting) //
XElement.ToString(SaveOptions.None)
XElement.ToString()
The XmlReaderSettings I am using for the XmlReader object are below. I tried IgnoreWhitespace =true/false with no luck but I cannot set it as true as some elements are skipped (for reason for skipping, see Why does XmlReader skip every other element if there is no whitespace separator?).
XmlReaderSettings xmlReaderSettings = new XmlReaderSettings();
xmlReaderSettings.ProhibitDtd = false;
//xmlReaderSettings.IgnoreWhitespace = true;//cannot use this setting
It works if I parse the XElement object but that defeats the whole purpose of using XmlReader as XElement.Parse() loads the xml in memory.
XElement el = XElement.ReadFrom(reader) as XElement;
XElement.Parse(el.ToString(), LoadOptions.None)
How can I remove the whitespace?
Edit: This is what I had to do:
The elements skipping is due to two reads reader.Read() and XElement.ReadFrom(reader) in the same iteration thereby skipping every other element. Fixing the loop mentioned in the link above solves that. The issue has nothing to do with XmlReaderSettings.
xelement.ToString(SaveOptions.DisableFormatting) removes the pretty formatting.

Try using this example form the XMLTextReader class. The XMLTextReader has a method "WhitespaceHandling", which you can set to none. It would be helpfull to answer this question, if you could have provided a test XML file, to test is XMLTextReader works.

Related

Xceed Docx ReplaceText always throwing newValue cannot be null.

I've tried a number of different options, but no matter what I do it either won't do anything or always return newValue error.
newValue cannot be null.
It seems I'm not the only one but it's had updates since the link below.
docX ReplaceText works incorrect
Below is my original example:-
if (sur.RequestType)
{
templateDoc.ReplaceText("[#1]", "x");
templateDoc.ReplaceText("[#2]", "");
}
else
{
templateDoc.ReplaceText("[#1]", "");
templateDoc.ReplaceText("[#2]", "x");
}
When debugging this it would get to line 4 then jump to line 9 where it would return the newValue cannot be null error on next step.
So I tried:-
string temp1 = "temp1";
if (sur.RequestType)
{
templateDoc.ReplaceText("[#1]", "x");
templateDoc.ReplaceText("[#2]", temp1, false, RegexOptions.IgnoreCase, paraFormat, paraFormat, MatchFormattingOptions.SubsetMatch);
}
else
{
templateDoc.ReplaceText("[#1]", "x.x");
templateDoc.ReplaceText("[#2]", "x", false, RegexOptions.IgnoreCase, paraFormat, paraFormat, MatchFormattingOptions.SubsetMatch);
}
Along with a couple other tweaks but all returning the same error.
Prior to using ReplaceText I'd used the example from the sample project:-
templateDoc.AddCustomProperty( new CustomProperty( "CompanySlogan", "Always with you" ) );
templateDoc.AddCustomProperty( new CustomProperty( "ClientName", "James Doh" ) );
Here it would step through each line but the produced document wouldn't have replaced anything.
Lastly more off topic but if anybody has a better solution, I'd been stuck going back and forth trying to output the file without saving it but had issues converting it from the Xceed DocX type to a HttpResponseMessage.
Below was my least favourable implementation of such as I'd either like to save it to a database or skip saving the file and just provide it directly to the user to save where they want instead of having a server side copy.
[HttpGet]
public HttpResponseMessage DownloadRecord(int id)
{
SURequest sur = _sURequestsService.GetRequestData(id);
var fullPath = System.Web.Hosting.HostingEnvironment.MapPath(#"~/Content/RequestForm.docx");
var fullPath2 = System.Web.Hosting.HostingEnvironment.MapPath(#"~/Content/RequestFormUpdated.docx");
var templateDoc = DocX.Load(fullPath);
var template = CreateRequestFromTemplate(templateDoc, sur);
template.SaveAs(fullPath2);
//using (FileStream fs2 = new FileStream(#"~/Content/RequestFormUpdated.docx", FileMode.Create))
//{
// template.SaveAs(fs2);
//}
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(fullPath2, FileMode.Open);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = Path.GetFileName(fullPath2);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentLength = stream.Length;
return result;
//return fs2;
}
I'm stuck with no clue how to proceed further with Xceed so am going to branch my present code and try using OpenXML to see if I have any better luck or if someone else can spot what I'm doing wrong or how to get past the issue in Xceed?
Any help would be much appreciated.
Turned out to be an issue with VS17 which was behaving stranging with replacetext and seemed to have cached an earlier issue in it's compiler.
This behaved like the issue was somewhere it wasn't and could only be resolved by manually stopping the compiler process.
Still no resolution for AddCustomProperty or with skipping generating a local file.
I'm going to work on trying to get it not to generate a local file but likely will need to either open a new question specific to that or setup something else to cleanup old files.

Is there any way of suppressing ‘Do you want to save changes to xxx.pdf before closing’ dialog using ABCpdf

We are reading the adobe form template using ABCpdf , populating form fields with values retrieved from database and amending them into a single PDF document and sending the document back as File stream in the HTTP response to the users in a ASP.net MVC App.
This approach is working fine and PDF documents are getting generated successfully. But when the user choose to open the generated PDF file and try to close it, they are being prompted ‘Do you want to save changes to xxx.pdf before closing’ dialog from Adobe Acrobat. Is there any way of suppressing this message using ABC pdf?.
Following is the code we are using to generate the PDF.
public byte[] GeneratePDF(Employee employee, String TemplatePath)
{
string[] FieldNames;
Doc theDoc;
MemoryStream MSgeneratedPDFFile = new MemoryStream();
//Get the PDF Template and read all the form fields inside the template
theDoc = new Doc();
theDoc.Read(HttpContext.Current.Server.MapPath(TemplatePath));
FieldNames = theDoc.Form.GetFieldNames();
//Navigate through each Form field and populate employee details
foreach (string FieldName in FieldNames)
{
Field theField = theDoc.Form[FieldName];
switch (FieldName)
{
case "Your_First_Name":
theField.Value = employee.FirstName;
break;
default:
theField.Value = theField.Name;
break;
}
//Remove Form Fields and replace them with text
theField.Focus();
theDoc.Color.String = "240 240 255";
theDoc.FillRect();
theDoc.Rect.Height = 12;
theDoc.Color.String = "220 0 0";
theDoc.AddText(theField.Value);
theDoc.Delete(theField.ID);
}
return theDoc.GetData();
}
Today I ran into this problem too, but with a PDF with no form fields. I ran #CharlieNoTomatoes code and confirmed the FieldNames collection was definitely empty.
I stepped through the various stages of my code and found that if I saved the PDF to the file system and opened from there it was fine. Which narrowed it down to the code that took the abcpdf data stream and sent it directly to the user (I normally don't bother actually saving to disk). Found this in the WebSuperGoo docs and it suggested my server might be sending some extra rubbish in the Response causing the file to be corrupted.
Adding Response.End(); did the trick for me. The resulting PDF files no longer displayed the message.
byte[] theData = _thisPdf.Doc.GetData();
var curr = HttpContext.Current;
curr.Response.Clear();
curr.Response.ContentType = "application/pdf";
curr.Response.AddHeader("Content-Disposition", "attachment; filename=blah.pdf");
curr.Response.Charset = "UTF-8";
curr.Response.AddHeader("content-length", theData.Length.ToString());
curr.Response.BinaryWrite(theData);
curr.Response.End();
I ran into this problem, as well. I found a hint about "appearance streams" here:
The PDF contains form fields and the NeedAppearances entry in the interactive form dictionary is set to true. This means that the conforming PDF reader will generate an appearance stream where necessary for form fields in the PDF and as a result the Save button is enabled. If the NeedAppearances entry is set to false then the conforming PDF reader should not generate any new appearance streams. More information about appearance streams in PDF files and how to control them with Debenu Quick PDF Library.
So, I looked for "appearance" things in the websupergoo doc and was able to set some form properties and call a field method to get rid of the "Save changes" message. In the code sample above, it would look like this:
Edit: After exchanging emails with fast-and-helpful WebSuperGoo support about the same message after creating a PDF with AddImageHtml that WASN'T fixed by just setting the form NeedAppearances flag, I added the lines about Catalog and Atom to remove the core document NeedAppearances flag that gets set during AddImageHtml.
public byte[] GeneratePDF(Employee employee, String TemplatePath)
{
string[] FieldNames;
Doc theDoc;
MemoryStream MSgeneratedPDFFile = new MemoryStream();
//Get the PDF Template and read all the form fields inside the template
theDoc = new Doc();
theDoc.Read(HttpContext.Current.Server.MapPath(TemplatePath));
FieldNames = theDoc.Form.GetFieldNames();
//Tell PDF viewer to not create its own appearances
theDoc.Form.NeedAppearances = false;
//Generate appearances when needed
theDoc.Form.GenerateAppearances = true;
//Navigate through each Form field and populate employee details
foreach (string FieldName in FieldNames)
{
Field theField = theDoc.Form[FieldName];
switch (FieldName)
{
case "Your_First_Name":
theField.Value = employee.FirstName;
break;
default:
theField.Value = theField.Name;
break;
}
//Update the appearance for the field
theField.UpdateAppearance();
//Remove Form Fields and replace them with text
theField.Focus();
theDoc.Color.String = "240 240 255";
theDoc.FillRect();
theDoc.Rect.Height = 12;
theDoc.Color.String = "220 0 0";
theDoc.AddText(theField.Value);
theDoc.Delete(theField.ID);
}
Catalog cat = theDoc.ObjectSoup.Catalog;
Atom.RemoveItem(cat.Resolve(Atom.GetItem(cat.Atom, "AcroForm")), "NeedAppearances");
return theDoc.GetData();
}

Access denied creating xml file in apache tomcat

I am creating an Exam Portal, in it there is a JSP calcresult.jsp which calculates the result of exam and shows the result also after that it creates an xml file which stores the result so that examiner can evaluate the result later.
here is the code for xml generation :
<%
DocumentBuilderFactory documentBuilderFactory =
DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder =
documentBuilderFactory.newDocumentBuilder();
Document document = documentBuilder.newDocument();
Element rootElement = document.createElement("Exam_Report");
document.appendChild(rootElement);
Element em = document.createElement("Name");
em.appendChild(document.createTextNode(session.getAttribute("userid").toString()));
rootElement.appendChild(em);
em = document.createElement("Exam_Id");
em.appendChild(document.createTextNode(session.getAttribute("examid").toString()));
rootElement.appendChild(em);
em = document.createElement("Paper_id");
em.appendChild(document.createTextNode(session.getAttribute("paperid").toString()));
rootElement.appendChild(em);
em = document.createElement("No_Of_Ques");
em.appendChild(document.createTextNode(request.getParameter("qid")));
rootElement.appendChild(em);
em = document.createElement("No_Of_Correct_Ques");
em.appendChild(document.createTextNode(""+right));
rootElement.appendChild(em);
em = document.createElement("Total_Marks");
em.appendChild(document.createTextNode(""+tmarks));
rootElement.appendChild(em);
em = document.createElement("Marks");
em.appendChild(document.createTextNode(""+marks));
rootElement.appendChild(em);
em = document.createElement("Percentage");
em.appendChild(document.createTextNode(""+percentage));
rootElement.appendChild(em);
em = document.createElement("Result");
em.appendChild(document.createTextNode(result));
rootElement.appendChild(em);
TransformerFactory transformerFactory =
TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(document);
StreamResult result1 = new StreamResult("CreateXML.xml");
transformer.transform(source, result1);
%>
everything works fine but when i run the page it shows an exception(Access Denied).
Well of course when i have to create a new page or file in server directory then i require administrative authority so what i did was to use absolute path which doesn't have any restriction like C:/xml/CreateXML.xml which really worked but now i am not able to access this xml page through AJAX.
So what is the best way to solve this problem. Any help will be really appreciated.
And well i am using Apache Tomcat as server.
One way would be to write a servlet to return the content of the XML file. Here's an example for a text file. For an xml file you should use "text/xml" as content type.
But a better way imo would be to avoid the creation of a local file and send the XML "on the fly" directly from the servlet. You can find an example here (the post is old but the code is still valid).

Algorithm or code for converting OMML to MathML

I am in the process of converting Word doc standard equations (OMML) to MathML using flash or Flex, please help me out by providing simple Algorithm or code snippet.
Thanks in advance,
Mani
There is an XSLT 1 stylesheet that does that conversion provided by microsoft as part of the Word Distribution, it is what handles placing MathML on the clipboard in Word. Typically installed as something like
c:/Program Files (x86)/Microsoft Office/Office14/OMML2MML.XSL
There is some discussion of an early version of this at
http://dpcarlisle.blogspot.co.uk/2007/04/xhtml-and-mathml-from-office-20007.html
here is snippet of a C# class I was working on a few days ago ... I know it's too late .. but for less future pain.
I think it's not very different in Action Script
the file OMML2MML.xsl is located at %ProgramFiles%\Microsoft Office\Office12\ as mentioned by #David the xsl file is used for placing MathML on the clipboard in Word and converting OMML to MML too.
public static string OMML(string omml)
{
XslCompiledTransform xslTransform = new XslCompiledTransform();
xslTransform.Load("OMML2MML.xsl");
using (XmlReader reader = XmlReader.Create(new StringReader(omml)))
{
using (MemoryStream ms = new MemoryStream())
{
XmlWriterSettings settings = xslTransform.OutputSettings.Clone();
// Configure xml writer to omit xml declaration.
settings.ConformanceLevel = ConformanceLevel.Fragment;
settings.OmitXmlDeclaration = true;
XmlWriter xw = XmlWriter.Create(ms, settings);
// Transform our OfficeMathML to MathML
xslTransform.Transform(reader, xw);
ms.Seek(0, SeekOrigin.Begin);
StreamReader sr = new StreamReader(ms, Encoding.UTF8);
string MathML = sr.ReadToEnd();
return MathML;
}
}
}

IsolatedFileStorage XML Reading Crash

Ok so, basically my problem is with reading and XML file from IsolatedFileStorage. I'll go through the process that leads to my error and then I'll list the relevant code and XML file.
On the first execution it recognises that the file does not exist - it therefore creates the file in IsolatedFileStorage
On the second execution it can now see that the file does exist and so it loads the XML file
On the third execution it can see that it exists - but it throws an XML error
I cannot for the life of me find a solution to it (link to other discussion on MSDN here)
So the code for reading/creating the XML file in IsolatedFileStorage is as follows:
try
{
/***********************
* CHECK THE SETTINGS
********************/
if (store.FileExists("AppSettings.xml"))
{
streamSettings = new IsolatedStorageFileStream("AppSettings.xml", System.IO.FileMode.Open, store);
DebugHelp.Text = "AppSettings.xml exists... Loading!";
streamSettings.Seek(0, System.IO.SeekOrigin.Begin);
xmlDoc = XDocument.Load(streamSettings, LoadOptions.None);
}
else
{
streamSettings = new IsolatedStorageFileStream("AppSettings.xml", System.IO.FileMode.Create, store);
DebugHelp.Text = "AppSettings.xml does not exist... Creating!";
xmlDoc = XDocument.Load("AppSettings.xml", LoadOptions.None);
}
if (xmlDoc != null)
xmlDoc.Save(streamSettings);
}
catch (Exception e)
{
DebugHelp.Text = e.ToString();
}
finally
{
streamSettings.Close();
}
And the related XML file is as follows:
<?xml version="1.0" encoding="utf-8" ?>
<Settings>
</Settings>
Extremely advanced I know - however it throws the following error (here) and you can find the full error text at the bottom of the Social.MSDN page.
Please help - I have been looking for a solution (as the one on the social.msdn site didn't work) for about 2 weeks now.
Why don't you try to read file using a simple StreamReader ? Below a part of a method I have created to readfile from store. Have a try, check your content, and then try loading xml from String (XDocument.Parse etc ...)
String fileContent = String.Empty;
using (_store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (_store.FileExists(file))
{
_storeStream = new IsolatedStorageFileStream(file, FileMode.Open, _store);
using (StreamReader sr = new StreamReader(_storeStream))
{
fileContent = sr.ReadToEnd();
}
__storeStream.Close();
return fileContent;
}
else {
return null;
}
}
It looks to me like the problem is in your save method - it looks like you are maybe appending the settings each time you close - to overwrite your existing settings, you need to ensure that you delete your existing file and create a new one.
To help debug this, try using http://wp7explorer.codeplex.com/ - this might help you see the raw file "on disk"
As an aside, for settings in general, do check out the AppSettings that IsolatedStorage provides by default - unless you have complicated needs, then these may suffice on their own.
Your code sample isn't complete so it's hard to say for sure but, rather than just seeking to the start of the file you may find it easier to just delete it if it already exists. You can do this with FileMode.Create. In turn this means you can do away with the need to check for the existing file.
I suspect that the problem is that you are writing a smaller amount of text to the file on subsequent attempts and so leaving part of the original/previous text behind. In turn this creates a file which contains invalid XML.

Resources