Using Vs 2010 I am editing a xsl file which will be used for transformation to output an xml file. I am trying to output a carriage return (
) and that only. I don't want the linefeed character (x0A) to appear.
No matter what kind of stunt I do in the xsl, the outputted file always adds a LF to my CR (CRLF) and I don't want that. The reason for why I want only the CR is that the output is parsed by a secondary system that sends sms-messages, which requires only LF.
I'm wondering if the problem is in the xsl or the transformation process.
The stylesheet:
<xsl:stylesheet xmlns:l="http://schemas.something.no/2008/" version='1.0'>
<xsl:import href='LydiaDateFuncs.xsl'/>
<xsl:template match='/'>
<xsl:apply-imports/>
</xsl:template>
<xsl:output method="xml" encoding="utf-8" indent="no" />
<xsl:template match="l:WorkOrderOccurrenceBE">
<Message>
<Body>
Adding cr here<xsl:text>
</xsl:text><xsl:text>
</xsl:text>No dice.
</Body>
</Message>
</xsl:template>
The code for transformation:
public static XmlDocument TransformObject(string xslFilepath, object serObj)
{
XmlDocument result = null;
xslTransf.Load(xslFilepath, new XsltSettings { EnableScript = true }, newXmlUrlResolver());
result = TransformObject(xslTransf, serObj);
}
public static XmlDocument TransformObject(XslCompiledTransform xslTransform, object transformObject)
{
XmlDocument result = null;
if (xslTransform != null)
{
DataContractSerializer serializer = new DataContractSerializer(transformObject.GetType());
string serializedObjValue = null;
using (MemoryStream stream = new MemoryStream())
{
serializer.WriteObject(stream, transformObject);
serializedObjValue = (new UTF8Encoding()).GetString(stream.ToArray());
}
if (serializedObjValue != null)
{
XmlDocument xmldoc = new XmlDocument();
xmldoc.LoadXml(serializedObjValue);
XmlDeclaration xmldec = xmldoc.CreateXmlDeclaration("1.0", "utf-8", null);
xmldoc.InsertBefore(xmldec, xmldoc.DocumentElement);
using (Stream stream = new MemoryStream())
{
xslTransform.Transform(xmldoc, null, stream);
stream.Position = 0;
using (StreamReader sr = new StreamReader(stream, Encoding.Unicode))
{
string xmlRes = sr.ReadToEnd();
result = new XmlDocument();
result.LoadXml(xmlRes);
}
}
}
}
return result;
}
Anybody been experiencing a similar issue?
One way to solve this problem is to use an XmlTextWriter in a respective overload of XslCompiledTransform.Transform()
This instnce of XmlTextWriter must have its Settings property set with an instance of XmlWriterSettings for which you have specified whatever newline characters you want as the value of the XmlWriterSettings.NewLineChars property.
See: http://msdn.microsoft.com/en-us/library/system.xml.xmlwriter.settings.aspx
and
http://msdn.microsoft.com/en-us/library/system.xml.xmlwritersettings.newlinechars.aspx
Related
I am trying to get a single node with an XPath, but i am getting a null value on the node, don' t know why
WebClient wc = new WebClient();
string nodeValue;
string htmlCode = wc.DownloadString("http://www.freeproxylists.net/fr/?c=&pt=&pr=&a%5B%5D=0&a%5B%5D=1&a%5B%5D=2&u=50");
HtmlAgilityPack.HtmlDocument html = new HtmlAgilityPack.HtmlDocument();
html.LoadHtml(htmlCode);
HtmlNode node = html.DocumentNode.SelectSingleNode("//table[#class='DataGrid']/tbody/tr[#class='Odd']/td/a");
nodeValue = (node.InnerHtml);
I see at least 2 mistakes in your xpath compared to the html you're trying to get information from.
There are no <a> that has <tr class=Odd"> as an ancestor.
Even if your Xpath had worked then you would only have gotten one <td> since you have decided to SelectSingleNode instead of SelectNodes
It looks like the are doing some kind of lazy protection from what you're trying to do. Since the a-tag is just represented in hexadecimal enclosed in IPDecode. So really it is no problem to extract the link. But the least you could have done was to look at the html before posting. You clearly have not tried at all. Since the html you're getting from your current code is not the <body> of the link you gave us - meaning you have to get the htmlpage from the absolute url or just use Selenium.
But since I am such a swell guy I will make your entire solution for you using Xpath, Html Agility Pack and Selenium. The following solutions gets the html of the site. then reads only the <tr> that has class="Odd". After that it finds all the "encrypted" <a> and decodes them into a string and writes them into an array. After that there is a small example of how to get an attribute value from one anchor.
private void HtmlParser(string url)
{
HtmlDocument htmlDoc = new HtmlAgilityPack.HtmlDocument();
htmlDoc.OptionFixNestedTags=true;
GetHTML(url);
htmlDoc.Load("x.html", Encoding.ASCII, true);
HtmlNodeCollection nodes = htmlDoc.DocumentNode.SelectNodes("//table[#class='DataGrid']/descendant::*/tr[#class='Odd']/td/script");
List<string> urls = new List<string>();
foreach(HtmlNode x in nodes)
{
urls.Add(ConvertStringToUrl(x.InnerText));
}
Console.WriteLine(ReadingTheAnchor(urls[0]));
}
private string ConvertStringToUrl(string octUrl)
{
octUrl = octUrl.Replace("IPDecode(\"", "");
octUrl = octUrl.Remove(octUrl.Length -2);
octUrl = octUrl.Replace("%", "");
string ascii = string.Empty;
for (int i = 0; i < octUrl.Length; i += 2)
{
String hs = string.Empty;
hs = octUrl.Substring(i,2);
uint decval = System.Convert.ToUInt32(hs, 16);
char character = System.Convert.ToChar(decval);
ascii += character;
}
//Now you get the <a> containing the links. which all can be read as seperate html files containing just a <a>
Console.WriteLine(ascii);
return ascii;
}
private string ReadingTheAnchor(string anchor)
{
//returns url of anchor
HtmlDocument anchorHtml = new HtmlAgilityPack.HtmlDocument();
anchorHtml.LoadHtml(anchor);
HtmlNode h = anchorHtml.DocumentNode.SelectSingleNode("a");
return h.GetAttributeValue("href", "");
}
//using OpenQA.Selenium; using OpenQA.Selenium.Firefox;
private void GetHTML(string url)
{
using (var driver = new FirefoxDriver())
{
driver.Navigate().GoToUrl(url);
Console.Clear();
System.IO.File.WriteAllText("x.html", driver.PageSource);
}
}
I was trying to export my C# list to Csv file. All is set well. But the thing is field seperator is not working properly. its showing like, my string with " at the end (eg: 0000324df"). Here is my Controller code.
IEnumerable stockexpo = stockexp; // Assign value
MemoryStream output = new MemoryStream();
StreamWriter writer = new StreamWriter(output, Encoding.UTF8);
writer.Write("ItemNo,");
writer.Write("Repeat Count");
writer.WriteLine();
foreach (StockResult order in stockexpo)
{
writer.Write(String.Format("{0:d}", order.ItemNumber));
writer.Write("\"");
writer.Write(",");
writer.Write("\"");
writer.Write(order.Count);
writer.Write("\"");
writer.Write(",");
writer.WriteLine();
}
writer.Flush();
output.Position = 0;
return File(output, "text/comma-separated-values", "stockexp.csv");
I need to know how i can seperate the field values appropriately. Anyone can help me for this.
writer.Write("\"");
This line of code will be outputting a " every time. Why have it at all?
Also, I wouldn't have a comma before the WriteLine, since there is no need to delimit the end of the file.
IEnumerable stockexpo = stockexp; // Assign value
MemoryStream output = new MemoryStream();
StreamWriter writer = new StreamWriter(output, Encoding.UTF8);
writer.Write("ItemNo,");
writer.Write("Repeat Count");
writer.WriteLine();
foreach (StockResult order in stockexpo)
{
writer.Write(order.ItemNumber);
writer.Write(",");
writer.Write(order.Count);
writer.WriteLine();
}
writer.Flush();
output.Position = 0;
return File(output, "text/comma-separated-values", "stockexp.csv");
I'm trying to create and export a XDocument on WP7.1.1 containing the following document type:
<!DOCTYPE xbel PUBLIC "+//IDN python.org//DTD XML Bookmark Exchange
Language 1.0//EN//XML"
"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd">
Unfortunately I was greeted with NotSupportedExceptions in all my attempts so far and I don't know how to go from here. Here is a little excerpt of things I tried:
/* create document */
var document = new XDocument();
var doctype = new XDocumentType("xbel", null, null, null);
document.AddFirst(doctype); // << everything working without this line
/* document header */
var version = new XAttribute("version", "1.0");
var root = new XElement("xbel", version);
document.Add(root);
/* convert to string1 */
var text1 = document.ToString(); // << NotSupportedException was unhandled
/* convert to string2 */
var stringBuilder = new StringBuilder();
var stringWriter = new StringWriter(stringBuilder);
document.Save(stringWriter); // << NotSupportedException was unhandled
var text2 = stringBuilder.ToString();
This problem might be related to this and this question.
Here is a hacky solution for my specific problem:
/* format */
var stringBuilder = new StringBuilder();
var stringWriter = new StringWriter(stringBuilder);
document.Save(stringWriter);
var text = stringBuilder.ToString();
/* document type */
const string subset = "<!DOCTYPE xbel PUBLIC \"+//IDN python.org//DTD XML Bookmark Exchange Language 1.0" +
"//EN//XML\" \"http://www.python.org/topics/xml/dtds/xbel-1.0.dtd\">";
return text.Replace("?>", "?>" + Environment.NewLine + subset);
It's always sad when the shortcomings and bugs of a framework force you to write strange code like this, but it's even worse when those encounters are as frequent as they are with Windows Phone.
I found I could generate XDocument object from html by using SgmlReader.SL.
https://bitbucket.org/neuecc/sgmlreader.sl/
The code is like this.
public XDocument Html(TextReader reader)
{
XDocument xml;
using (var sgmlReader = new SgmlReader { DocType = "HTML", CaseFolding = CaseFolding.ToLower, InputStream = reader })
{
xml = XDocument.Load(sgmlReader);
}
return xml;
}
Also we can get src attributes of img tags from the XDocument object.
var ns = xml.Root.Name.Namespace;
var imgQuery = xml.Root.Descendants(ns + "img")
.Select(e => new
{
Link = e.Attribute("src").Value
});
And, we can download and convert stream data of image to BASE64 string.
public static string base64String;
WebClient wc = new WebClient();
wc.OpenReadAsync(new Uri(url)); //image url from src attribute
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
using (MemoryStream ms = new MemoryStream())
{
while (true)
{
byte[] buf = new byte[32768];
int read = e.Result.Read(buf, 0, buf.Length);
if (read > 0)
{
ms.Write(buf, 0, read);
}
else { break; }
}
byte[] imageBytes = ms.ToArray();
base64String = Convert.ToBase64String(imageBytes);
}
}
So, What I'd like to do is bellow steps. I'd like to do bellow steps in one method chain like LINQ or Reactive Extensions.
Get src attributes of img tags from XDocument object.
Get image datas from urls.
Generate BASE64 string from image datas.
Replace src attributes by BASE64 string.
The simplest source and output are here.
Before
<html>
<head>
</head>
<body>
<img src='http://image.com/image.jpg' />
<img src='http://image.com/image2.png' />
</body>
</html>
After
<html>
<head>
</head>
<body>
<img src='data:image/jpg;base64,iVBORw...' />
<img src='data:image/png;base64,iSDoske...' />
</body>
</html>
Does anyone know the solution for this?
I'd like to ask experts.
Both LINQ and Rx are designed to promote transformations that result in new objects, not ones that modify existing objects, but this is still doable. You have already done the first step, breaking the task into parts. The next step is to make composable functions that implement those steps.
1) You mostly have this one already, but we should probably keep the elements around to update later.
public IEnumerable<XElement> GetImages(XDocument document)
{
var ns = document.Root.Name.Namespace;
return document.Root.Descendants(ns + "img");
}
2) This seems to be where you have hit a wall from the composability point of view. To start, lets make a FromEventAsyncPattern observable generator. There are already ones for the Begin/End async pattern and standard events, so this will come out somewhere in between.
public IObservable<TEventArgs> FromEventAsyncPattern<TDelegate, TEventArgs>
(Action method, Action<TDelegate> addHandler, Action<TDelegate> removeHandler
) where TEventArgs : EventArgs
{
return Observable.Create<TEventArgs>(
obs =>
{
//subscribe to the handler before starting the method
var ret = Observable.FromEventPattern<TDelegate, TEventArgs>(addHandler, removeHandler)
.Select(ep => ep.EventArgs)
.Take(1) //do this so the observable completes
.Subscribe(obs);
method(); //start the async operation
return ret;
}
);
}
Now we can use this method to turn the downloads into observables. Based on your usage, I think you could also use DownloadDataAsync on the WebClient instead.
public IObservable<byte[]> DownloadAsync(Uri address)
{
return Observable.Using(
() => new System.Net.WebClient(),
wc =>
{
return FromEventAsyncPattern<System.Net.DownloadDataCompletedEventHandler,
System.Net.DownloadDataCompletedEventArgs>
(() => wc.DownloadDataAsync(address),
h => wc.DownloadDataCompleted += h,
h => wc.DownloadDataCompleted -= h
)
.Select(e => e.Result);
//for robustness, you should probably check the error and cancelled
//properties instead of assuming it finished like I am here.
});
}
EDIT: As per your comment, you appear to be using Silverlight, where WebClient is not IDisposable and does not have the method I was using. To deal with that, try something like:
public IObservable<byte[]> DownloadAsync(Uri address)
{
var wc = new System.Net.WebClient();
var eap = FromEventAsyncPattern<OpenReadCompletedEventHandler,
OpenReadCompletedEventArgs>(
() => wc.OpenReadAsync(address),
h => wc.OpenReadCompleted += h,
h => wc.OpenReadCompleted -= h);
return from e in eap
from b in e.Result.ReadAsync()
select b;
}
You will need to find an implementation of ReadAsync to read the stream. You should be able to find one pretty easily, and the post was long enough already so I left it out.
3 & 4) Now we are ready to put it all together and update the elements. Since step 3 is so simple, I'll just merge it in with step 4.
public IObservable<Unit> ReplaceImageLinks(XDocument document)
{
return (from element in GetImages(document)
let address = new Uri(element.Attribute("src").Value)
select (From data in DownloadAsync(address)
Select Convert.ToBase64String(data)
).Do(base64 => element.Attribute("src").Value = base64)
).Merge()
.IgnoreElements()
.Select(s => Unit.Default);
//select doesn't really do anything as IgnoreElements eats all
//the values, but it is needed to change the type of the observable.
//Task may be more appropriate here.
}
How to parser this xml content.
<Content>
<caption> Today Headline </caption>
<s1>
<name>6</name>
<name>4</name>
<name>4</name>
</s1>
<s2>
<name>3</name>
<name>6</name>
<name>0</name>
</s2>
</Content>
Mycode:
date = (from story
in xmlParser.Descendants("s1")
select new EspnViewModel
{
Category = story.Element("name").Value,
}).ToList();
return data;
I'm having a hard time trying to figure out how to parse everything out.
Why dont you use xmlParser.Descendants("name") instead?
EDIT:
var caption = xmlParser.Descendants("caption").First().InnerText;
var names = from story in xmlParser.Descendants("name")
select new EspnViewModel
{
Category = story.InnerText
}).ToList();
Note: I am writing this in haste, but you get the idea..
private List<yourclass> ReadList()
{
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
if (myIsolatedStorage.FileExists("xmlName.xml"))
{
using (IsolatedStorageFileStream stream = myIsolatedStorage.OpenFile("xmlName.xml", FileMode.Open))
{
XmlSerializer serializer = new XmlSerializer(typeof(List<your class>));
List<yourclass> data = (List<yourclass>)serializer.Deserialize(stream);
return data.ToList();
}
}
else
{
return null;
}
}
}