<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Autokinetic Effect - Erik Saltwell's Weblog</title><link>http://blogs.msdn.com/eriksalt/default.aspx</link><description>All things System.Xml</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>My brush with the dark side</title><link>http://blogs.msdn.com/eriksalt/archive/2005/11/10/DontComeToTheDarkSide.aspx</link><pubDate>Thu, 10 Nov 2005 20:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:491512</guid><dc:creator>eriksalt</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/eriksalt/comments/491512.aspx</comments><wfw:commentRss>http://blogs.msdn.com/eriksalt/commentrss.aspx?PostID=491512</wfw:commentRss><description>&lt;P&gt;Attention all MS Field personnel: Anyone who would like to come over to my office and slap me around, I will be available between 2:00 and 4:00...&lt;/P&gt;
&lt;P&gt;I spent the first four years of my career here at Microsoft as part of Microsoft Consulting Services in NYC. One of my biggest pet peeves was that, when you interacted with the product teams, their answer for everything seemed to be&lt;/P&gt;&lt;CODE&gt;"Well, upgrade to &lt;I&gt;&amp;lt;place-product-name-here&amp;gt;&lt;/I&gt; and everything will be better."&lt;/CODE&gt; 
&lt;P&gt;When customers come to you with issues, they clearly don't want to be up sold, they want their problem solved (duh).&lt;/P&gt;
&lt;P&gt;Unfortunately, just a year after moving to Redmond, I almost found myself committing that same atrocity today. We have a customer who makes heavy use of xslt, and all the xslt work is eating up allot of cycles, and they asked us for some advice. Now, we have put a HUGE amount of work into increasing the performance of Whidbey, and you can see the results of that work in the product, so my first thought was 'Well, if you want to increase perf, why not move from your current engine to Whidbey?' 
&lt;P&gt;At this point I could hear Emperor Palpatine's voice in my head going 'Yes... Feel the upgrading flow through you. Come to the dark side...' I do think that there are benefits to upgrading here, especially for perf, but I was clearly focused on my product a little bit more then I was on the customer. So I wanted to offer an official apology to all my friends and peers in the field. I shall not be tempted again... &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=491512" width="1" height="1"&gt;</description></item><item><title>Erik gets a taste of the good stuff</title><link>http://blogs.msdn.com/eriksalt/archive/2005/10/30/UsabilityStudies.aspx</link><pubDate>Sun, 30 Oct 2005 22:32:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:487083</guid><dc:creator>eriksalt</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/eriksalt/comments/487083.aspx</comments><wfw:commentRss>http://blogs.msdn.com/eriksalt/commentrss.aspx?PostID=487083</wfw:commentRss><description>&lt;P&gt;(I know I promised to write some more about Linq and XLinq, which I will do, but I have had some other thoughts on my mind as well that need to get out before my head explodes, so I am going to be pushing out a few notes about other stuff before returning back to Linq in the near future). &lt;/P&gt;
&lt;P&gt;Wow.&lt;/P&gt;
&lt;P&gt;I had an amazing thing happen recently and I wanted to blog about it because it's had quite a powerful effect on me.&lt;/P&gt;
&lt;P&gt;Recently, I had the opportunity to proctor a usability study for the XmlReader. If you have not heard of a usability study, I will explain. In a usability study you craft a few small tasks, such as:&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;Read in some xml and validate that the xml conforms to some schema.&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;You then get a bunch of developers together - we have a team at Microsoft who is responsible for finding developers, so most of the people taking the study are &lt;B&gt;not&lt;/B&gt; MS employees - and you have them implement these tasks, all while you record everything they code as well as whatever they say. Then, after you run enough people through the study you collect the feedback in order to decide how to make improvements to your API. Of course it gets more complicated then this, you can head over to &lt;A HREF="/stevencl/default.aspx"&gt;http://blogs.msdn.com/stevencl/default.aspx&lt;/A&gt;&amp;nbsp;if you would like to know more, but that's the gist of it. A part of the study is that every time a subject comes in to participate, we have a team member sit in so that they can provide help if the person gets stuck, and that's where I come into the picture...&lt;/P&gt;
&lt;P&gt;I recently had the opportunity to be one of these proctors, and for me it was like finding religion... Or perhaps like doing heroin (or I imagine that is what it would be like, anyhow)...&lt;/P&gt;
&lt;P&gt;Well. whatever the metaphor, I definitely walked away wanting more. There were some many small things you can see when someone is using your API, like which pieces they blow right through and which pieces they stumble over, or how they interact with the API. These are all things that were amazing to me. &lt;/P&gt;
&lt;P&gt;Ok, so maybe that means I didn't really grok our API in the first place, but I don't really believe that. The funny thing for me is that there are many ways in which having a huge, diverse customer base, like the customer base for Whidbey, can actually impede your ability to get the kind of feedback you would like to have, but (just to beat the drug metaphor to death) usability studies definitely feel like you're mainlining customer feedback. &lt;/P&gt;
&lt;P&gt;Now, there are no silver bullets in software development, but for anyone who is interested in having an API which is easy to use, I would definitely recommend adding this tool to your toolkit (again, you can find more details at &lt;A HREF="/stevencl/default.aspx"&gt;http://blogs.msdn.com/stevencl/default.aspx&lt;/A&gt;). &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=487083" width="1" height="1"&gt;</description></item><item><title>From IUnknown to IEnumerable</title><link>http://blogs.msdn.com/eriksalt/archive/2005/09/28/IUnknown2IEnumerable.aspx</link><pubDate>Wed, 28 Sep 2005 16:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:474937</guid><dc:creator>eriksalt</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/eriksalt/comments/474937.aspx</comments><wfw:commentRss>http://blogs.msdn.com/eriksalt/commentrss.aspx?PostID=474937</wfw:commentRss><description>&lt;P&gt;The core piece of Linq is a query language which can query many, many kinds of data. Of course, its the 'many' part which is difficult to get right. The tricky part is that, if you are going to query different kinds data, you have to specify something that all your data types have in common, and then build your query language on top of that commonality. &lt;BR&gt;&lt;BR&gt;Take SQL &amp;amp; ODBC, which together form a technology that can be used to access many different kinds of data and provide a query language for that data using SQL. Over the years we have seen ODBC drivers that can query SqlServer, DB2, Oracle, and MSAccess. Of course ODBC drivers have provided access to more then just databases, there are ODBC drivers for Excel, text files and a host of other common data sources. What they all have in common is that this data is rectangular: it is made up of rows and columns. This makes sense because ODBC and SQL were designed for database access and databases are traditional stores of rectangular data, which is why using ODBC drivers to access non-rectangular data requires so much duct tape. This is not just about the SOURCE data being rectangular, in SQL the RESULTS are also primarily returned as rectangles. If you were thinking about generating a more general query language which can handle other types of data - like xml - you would need to be able to handle more then just this (not to mention the fact that you would want the creation of new data sources to be much easier then it was in ODBC).&lt;BR&gt;&lt;BR&gt;For Linq, the commonality between the types of data you can query is that they all need to implement IEnumerable and, more frequently, its generic cousin IEnumerable&amp;lt;&amp;gt; (there is some simplification here for remote data sources, a simplification I hope to return to in a later post, but from a high level this is accurate). Once you start working with Linq for any real length of time, you will start to realise that IEnumerable&amp;lt;&amp;gt; is looking less like 'just another datatype' and more like a first class citizen of the language. Query expressions (i.e. the 'from ... select' syntax for querying in Linq) are designed to work over IEnumerable's as its data sources, and it returns IEnumerable's as the result. &lt;BR&gt;&lt;BR&gt;Using IEnumerable as your common format is a good choice for a number of reasons, but the ones that impress me are:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;It is familiar to developers.&lt;/LI&gt;
&lt;LI&gt;It is easy to implement, especially using C# 2.0's "yield return" syntax. If your data is already contained in the .Net collection classes, then you don't even need to do that.&lt;BR&gt;With the appearance of generics, IEnumerable&amp;lt;&amp;gt; can declare what type of object it is enumerating over. Anyone who remembers the collection interfaces in COM will remember how much a collection of IUnknown (or Object in .Net) can obfuscate your object model.&lt;/LI&gt;
&lt;LI&gt;Because the enuerated type can be any .Net type, the returned data can have a variety of shapes, and is not restricted to being rectangular. Using XLinq, you can query and have that data returned as an xml fragment.&lt;/LI&gt;
&lt;LI&gt;IEnumerable&amp;lt;&amp;gt; is a streaming interface over a collection of objects. What do I mean by streaming? Think of the difference between DataReader and DataSet, or between XmlReader and XmlDocument. The readers in these examples are both streaming interfaces, because they don't force you to allocate the whole collection at one time. With IEnumerable&amp;lt;&amp;gt;, you retrieve an IEnumerator on which you constantly call MoveNext() and Current, which means you don't have to allocate the whole collection of items being enumerated over at one time.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Let me give you an example; In DLink you can directly execure your own SQL statements (including stored procedures) by calling the ExecuteQuery method:&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;IEnumerable&amp;lt;Customer&amp;gt; customers = db.ExecuteQuery&amp;lt;Customer&amp;gt;("exec GetCustomersProc");&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;This is the general 'escape hatch' for using DLinq without the O/R mapping. The results that come back from this query get converted into Customer objects (one for each returned row) that are exposed through an IEmumerable&amp;lt;Customer&amp;gt; What is nice is that:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;You get back strongly typed data.&lt;/LI&gt;
&lt;LI&gt;You get back an IEnumerable, so you can use these results in other Linq querries.&lt;/LI&gt;
&lt;LI&gt;Because you get back an IEnumerable, each Customer object can be retrieved when you call MoveNext(), so if you get back a billion rows, you don't have to allocate all billion Customer objects at one point in memory.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;It will be interesting to know if in 3 years we don't see people talking about the pervasiveness of IEnumerable similar to how people used to talk about IUnknown. I wait for the first IENMRBL license plate with bated breath...&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=474937" width="1" height="1"&gt;</description></item><item><title>PDC and Linq, two great tastes...</title><link>http://blogs.msdn.com/eriksalt/archive/2005/09/21/LinqIntroduction.aspx</link><pubDate>Wed, 21 Sep 2005 16:44:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:472417</guid><dc:creator>eriksalt</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/eriksalt/comments/472417.aspx</comments><wfw:commentRss>http://blogs.msdn.com/eriksalt/commentrss.aspx?PostID=472417</wfw:commentRss><description>&lt;P&gt;I had the great pleasure of helping to represent one of Microsoft's new technologies at the PDC this year, its called LINQ; Language INtegrated Query.&amp;nbsp; I hope to provide a number of posts about the details of LINQ and XLinq over the next few weeks, but I thought I should start with a simple introduction first, for everyone who was not able to make it to this event.&lt;/P&gt;
&lt;P&gt;LINQ is a collection of new language features (which are planned to be included in future versions of C# and VB.Net) and new framework APIs that allow you to query and transform "data" from directly within the language.&amp;nbsp; There are two interesting things to note about this sentence:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Notice the finger-quotes around the term "data" in the sentence above.&amp;nbsp; The core of LINQ is a collection of new language features that allow you to query almost any kind of data (as long as it is exposed in a certain way) without ever having to leave the comfort off your favorite programming language (we will get to the details of what a data provider needs to do in order to work with LINQ later).&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;When Microsoft ships LINQ, it will also ship new API's for some kinds of data sources (the plan now is to ship APIs for XML and SqlServer, and LINQ already works with the current .Net collection classes) that can be queried using LINQ.&amp;nbsp; That's why I was there, to represent the LINQ-enabled XML API.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;In other words, LINQ is a syntax for querying data directly in the language , but it does not specify WHAT KIND of data is being queried (this statement is slightly inaccurate, because it is not technically a 'syntax' but rather a collection of language features which are implemented with different syntax for different languages, but we can gloss over that for the moment).&amp;nbsp; Anyone can choose to implement their APIs in a way that allows LINQ language features to query that data.&amp;nbsp; Now you may be thinking that this is already true with today's technology.&amp;nbsp; After all, if you implement an OLE DB provider for your data, then you can query it using SQL.&amp;nbsp;&amp;nbsp; There are (at least) three major issues with this:&lt;BR&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;You effectively need a post-graduate degree in the OLE DB architecture before you would consider writing an OLE DB provider 'easy'.&amp;nbsp; In LINQ, you expose you data as IEnumerable's, just like the existing collection classes.&amp;nbsp; This makes exposing your data in a LINQ friendly way very easy.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;In fact, if your data is already represented as an in-memory object model, there is a good chance your data already is in the correct format.&lt;/LI&gt;
&lt;LI&gt;SQL is designed around providing access to 'rectangular' data (rows and columns) whereas some data (like XML) is better expressed in other ways.&amp;nbsp; Since LINQ is designed to access many different types of data, it does not make assumptions about the shape or structure of your data.&lt;BR&gt;Since your computer language's compiler knows nothing about SQL, you get no compile-time syntax checking.&amp;nbsp; Since LINQ is a part of the programming language, you get a much better compile-time experience.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&lt;BR&gt;To put it another way:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;If you've ever wanted to do a join between an xml file and data in your database, then LINQ is for you.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;If you get tired every time a new data format comes out because that's another query language you will burn 3 weekends learning, then LINQ is for you.&amp;nbsp; &lt;/LI&gt;
&lt;LI&gt;If you wish that your programming language's compiler validated your queries for you, rather then having to run each query to make sure you got the syntax right, then LINQ is for you.&lt;BR&gt;&amp;nbsp;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Ok, so LINQ is all about enhancing developer productivity when working with data.&amp;nbsp; So what does a LINQ query look like? The following simple example shows us one way to query some xml data using LINQ and the new LINQ-Enabled XML API:&lt;/P&gt;&lt;CODE&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IEnumerable&amp;lt;XElement&amp;gt; transactions =&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;from&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;transaction in myXmlElement.Element("AllTransactions").Elements("Transaction") &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; where &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (double)transaction.Attribute("amount") &amp;gt; 1000.0 &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; transaction;&lt;/CODE&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;This query returns all the 'Transaction' elements that are children of an "AllTransactions" element which is itself a child of myXmlElement and that have an 'amount' attribute whose value is greater then $1000.00.&amp;nbsp; This could also be expressed with the following XPath: &lt;/P&gt;
&lt;P&gt;&lt;/P&gt;&lt;CODE&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; AllTransactions/Transaction[@amount&amp;gt;1000.00]&lt;/P&gt;&lt;CODE&gt;
&lt;P&gt;Now if you already understand XPath, then you are probably thinking 'Why would I move to a verbose syntax like LINQ when the XPath is so much more compressed?' Which is a fair statement, but it misses the point.&amp;nbsp; The point is that I can use the same syntax to query my database:&lt;/P&gt;&lt;CODE&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;Individual&amp;gt; individuals =&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;from&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; individual in myDatabase.Individuals&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; individual.Role=="Supreme Commander"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; individual;&lt;/P&gt;&lt;/CODE&gt;
&lt;P&gt;And you can use the same syntax to query collections of in-memory objects:&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;char&amp;gt; firstInitials = &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name in myNameList&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;where&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name.Length&amp;lt;0&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;select&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; name[0];&lt;/P&gt;
&lt;P&gt;Or you can do a join between xml and your database (sorry for the complicated example here):&lt;/P&gt;
&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IEnumerable&amp;lt;XElement&amp;gt; transactions = &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; from&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; individual in myDatabase.Individuals,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; transaction in report.Element("AllTransactions).Elements("Transaction")&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; where&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; individual.Name ==&amp;nbsp; (string)transaction.Attribute("name")&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;&amp;amp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; individual.Role=="Supreme Commander"&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;&amp;amp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (double)transaction.Attribute("amount") &amp;gt; 1000.0&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; transaction;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;The point is, LINQ is a general purpose language for querying and transforming data, so of course there will be cases where a domain-specific query language (like xslt) will be more powerful, more compact, or more expressive.&amp;nbsp; Our hope though, is that for those common cases where you don't need the extra power, this will be (as one PDC-goer put it) 'the last weird query language you'll ever have to learn.'&amp;nbsp; &lt;BR&gt;&lt;/P&gt;&lt;/CODE&gt;&lt;/CODE&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=472417" width="1" height="1"&gt;</description></item><item><title>Please Recycle...</title><link>http://blogs.msdn.com/eriksalt/archive/2005/08/15/RecycleYourNametables.aspx</link><pubDate>Mon, 15 Aug 2005 21:07:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:451905</guid><dc:creator>eriksalt</dc:creator><slash:comments>10</slash:comments><comments>http://blogs.msdn.com/eriksalt/comments/451905.aspx</comments><wfw:commentRss>http://blogs.msdn.com/eriksalt/commentrss.aspx?PostID=451905</wfw:commentRss><description>&lt;P&gt;(My post today is on a topic some of you may already be familiar with - reusing NameTable across Xml messages.&amp;nbsp; If so, please feel free to skip this entry.&amp;nbsp; I posted it because, while I have seen other press on this issue, I thought it was important enough that I wanted to get more information out there.)&lt;/P&gt;
&lt;P&gt;For anyone who has not met him yet, I would like to introduce you to an old friend, XmlNameTable. XmlNameTable is an interface used by XmlReader and XmlDocument when they want to store atomized names. For example, imagine that you parsed the following document:&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff&gt;&amp;lt;?&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;xml&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;version&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="1.0"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;encoding&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="utf-8"&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;?&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;stable&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;horse&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Mr. Ed&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;horse&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;horse&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Seabicuit&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;horse&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;horse&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Man O' War&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;horse&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&lt;FONT color=#006400&gt;&amp;lt;!-- Imagine 10,000 more horses here --&amp;gt;&lt;/FONT&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;horse&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;Quick Draw McGraw&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;horse&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;stable&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;Then you use the following code:&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;&lt;FONT face=Arial&gt;System.Xml.&lt;FONT color=#008000&gt;XmlReader&lt;/FONT&gt; reader = &lt;FONT color=#008000&gt;XmlReader&lt;/FONT&gt;.Create(…);&lt;BR&gt;&lt;FONT color=#008000&gt;List&lt;/FONT&gt;&amp;lt;&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;&amp;gt; elementNames=new &lt;FONT color=#008000&gt;List&lt;/FONT&gt;&amp;lt;&lt;FONT color=#0000ff&gt;string&lt;/FONT&gt;&amp;gt;();&lt;BR&gt;reader.MoveToContent();&lt;BR&gt;&lt;FONT color=#0000ff&gt;while&lt;/FONT&gt;(reader.Read())&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#0000ff&gt;if&lt;/FONT&gt;(reader.NodeType==&lt;FONT color=#008000&gt;XmlNodeType&lt;/FONT&gt;.Element)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; elementName.Add(reader.Name);&lt;BR&gt;}&lt;/FONT&gt; &lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;How many copies of the string "horse" do you expect to find contained in elementNames?&lt;/P&gt;
&lt;P&gt;The answer is that the list will contain 10,000 or so references to only one string. This is because each time the parser comes upon a name, it checks to see if that name already exists in its XmlNameTable, and if so it uses that copy of the name.&amp;nbsp; This not only decreases memory pressure, but it also allows you to do reference comparisons for names.&lt;/P&gt;
&lt;P&gt;If you look at the XmlReaderSettings class, you will see that it contains a NameTable property that takes an implementation of XmlNameTable.&amp;nbsp; This property exists so that you can pass in your own XmlNameTable when you create a new reader through the XmlReader.Create(…) API.&amp;nbsp; Doing this allows you to pass in your own implementation of XmlNameTable, which is mildly useful in some odd scenarios.&amp;nbsp; More importantly, this also allows you to re-use a name table across multiple documents, which can be an important performance optimization, particularly when parsing many small documents that have similar names.&lt;/P&gt;
&lt;P&gt;For example, let's say that you had some xml that represented a purchase order:&lt;/P&gt;
&lt;P&gt;&lt;CODE&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff&gt;&amp;lt;?&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;xml&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;version&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="1.0"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;encoding&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="utf-8"&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;?&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;purchaseOrder&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;poNumber&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff&gt;="111"&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp; &lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;customer&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;name&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff&gt;="Mr. Ed"&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;lineItems&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;lineItem&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;itemType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="horseshoe"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;quantity&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="4"&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;/&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;lineItem&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;itemType&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="saddle"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;quantity&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;="1"&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;/&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;lineItems&lt;/FONT&gt;&lt;/FONT&gt;&lt;FONT face=Arial&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp; &lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;customer&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;purchaseOrder&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;If&amp;nbsp; you have to process many of these purchase orders but use different name tables each time you process the message, you will continually have the overhead of allocating the names 'purchaseOrder', 'customer, name', 'lineItems', 'lineItem', 'itemType' and 'quantity' over and over.&amp;nbsp; You will also have to allocate new entries in the underlying collection class used by the XmlNameTable.&amp;nbsp; If instead you reuse your NameTable across readers, you can see quite a bit of savings.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;In order to understand these differences, I ran a test.&amp;nbsp; I created two xml documents.&amp;nbsp; The first document was similar to the 'stable' sample above, where there were very few unique names, and some of the names ('horse' in this case) were repeated over and over.&amp;nbsp; The second document was similar to the 'purchaseOrder' sample, where just about every name in the document was unique, although my document was somewhat larger then the sample shown above).&amp;nbsp; &lt;/P&gt;
&lt;P&gt;I parsed each of these documents 100,000 times.&amp;nbsp; In half of these cases I reused the same name table.&amp;nbsp; In the other half I recreated the name table each time I parsed the document.&lt;/P&gt;
&lt;P&gt;Here are my results:&lt;BR&gt;
&lt;TABLE cellSpacing=2 cellPadding=2 border=1&gt;
&lt;TR&gt;
&lt;TD vAlign=top&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;FONT face="Courier New" size=2&gt;Repeating Names (stable)&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD vAlign=top size="2" face="Courier New" &lt;&lt;FONT&gt;Unique Names&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top&gt;&lt;FONT face="Courier New" size=2&gt;Re-use name table&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;FONT face="Courier New" size=2&gt;2.596 seconds&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;FONT face="Courier New" size=2&gt;1.308 seconds&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;
&lt;TR&gt;
&lt;TD vAlign=top&gt;&lt;FONT face="Courier New" size=2&gt;Don’t re-use name table&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;FONT face="Courier New" size=2&gt;2.696 seconds&lt;/FONT&gt;&lt;/TD&gt;
&lt;TD vAlign=top&gt;&lt;FONT face="Courier New" size=2&gt;1.771 seconds&lt;/FONT&gt;&lt;/TD&gt;&lt;/TR&gt;&lt;/TABLE&gt;&lt;/P&gt;
&lt;P&gt;As you can see, the performance improvement looks roughly like this:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Xml with many repeating names (and very few unique ones): 3.7% improvement. 
&lt;LI&gt;Xml with many unique names (and very few repeating ones): 26.1% improvement.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;This makes sense.&amp;nbsp; If your document consists of the same names repeating over and over again, then you will not spend much of your time parsing names over and over.&amp;nbsp; If, on the other hand, you have a small document, or one with many unique names, then you will spend a proportionately higher percentage of your time in name management.&amp;nbsp; Make sure you measure your case, since your mileage will vary depending on the shape of your xml.&lt;/P&gt;
&lt;P&gt;There are two things you need to be careful of when re-using your name table:&lt;BR&gt;&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;Watch out for multithreading: The default implementation is not thread-safe.&amp;nbsp; If you are parsing on multiple threads using the same name table, you will either need to roll your own, thread-safe implementation or use one name table per thread (perhaps storing it in thread-local storage). 
&lt;LI&gt;Watch out for name-bloat: If you are parsing untrusted data, a malicious hacker can send you a large number of different names, each of which will be added to the name table.&amp;nbsp; Over time this can starve your application of memory.&amp;nbsp; Even without hackers, you may see the size of your name table grow if your parse many xml messages with different names.&amp;nbsp; For these reasons, you may want to occasionally clear the table out.&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=451905" width="1" height="1"&gt;</description></item><item><title>Priya on Unique Particle Attribution</title><link>http://blogs.msdn.com/eriksalt/archive/2005/08/09/449612.aspx</link><pubDate>Tue, 09 Aug 2005 20:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:449612</guid><dc:creator>eriksalt</dc:creator><slash:comments>8</slash:comments><comments>http://blogs.msdn.com/eriksalt/comments/449612.aspx</comments><wfw:commentRss>http://blogs.msdn.com/eriksalt/commentrss.aspx?PostID=449612</wfw:commentRss><description>&lt;P&gt;Priya Lakshminarayanan, ruler of all things schema, has just posted an article on UPA errors (that's 'Unique Particle Attribution') that does a great job of presenting a very complicated schema issue very clearly.&amp;nbsp; I would guess that even major schema geeks will learn a thing or two from the post.&amp;nbsp; Go check it out &lt;a href="http://blogs.msdn.com/xmlteam/archive/2005/08/09/449569.aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=449612" width="1" height="1"&gt;</description></item><item><title>What the heck is OutputSettings</title><link>http://blogs.msdn.com/eriksalt/archive/2005/07/27/OutputSettings.aspx</link><pubDate>Wed, 27 Jul 2005 16:22:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:443881</guid><dc:creator>eriksalt</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/eriksalt/comments/443881.aspx</comments><wfw:commentRss>http://blogs.msdn.com/eriksalt/commentrss.aspx?PostID=443881</wfw:commentRss><description>Oleg Tkachenko over at Signs in the Sand had a recent blog post about the OutputSettings property of XslCompiledTransform.&amp;nbsp; He posted this example usage:&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Courier New" size=2&gt;&lt;FONT color=#0000ff&gt;using&lt;/FONT&gt; (&lt;FONT color=#008000&gt;XmlReader&lt;/FONT&gt; src = &lt;FONT color=#008000&gt;XmlReader&lt;/FONT&gt;.Create("../../source.xml"))&lt;BR&gt;{&lt;BR&gt;&lt;FONT color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; XslCompiledTransform&lt;/FONT&gt; xslt = &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; XslCompiledTransform();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xslt.Load("../../style.xslt");&lt;BR&gt;&lt;FONT color=#008000&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; XmlWriter&lt;/FONT&gt; result = &lt;FONT color=#008000&gt;XmlWriter&lt;/FONT&gt;.Create(Console.Out, xslt.OutputSettings);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xslt.Transform(src, &lt;FONT color=#0000ff&gt;null&lt;/FONT&gt;, result, &lt;FONT color=#0000ff&gt;new&lt;/FONT&gt; XmlUrlResolver());&amp;nbsp;&lt;BR&gt;}&lt;/FONT&gt;&lt;BR&gt;&lt;BR&gt;We have also received some feedback that this was somewhat confusing, so I figured I would explain a little bit more about what this 'OutputSettings' property is and why it exists.&lt;BR&gt;When we first thought about creating the XslCompiledTransform class, we figured that we would use an XmlWriter to render the output of the transform.&amp;nbsp; This made sense for a few reasons:&lt;BR&gt;
&lt;UL&gt;
&lt;LI&gt;It provided for a good separation of responsibilities (disaggregation)&lt;/LI&gt;
&lt;LI&gt;This separation follows the intent of the xslt design committee to separate serialization from transformation&lt;/LI&gt;
&lt;LI&gt;It allowed users to pass in their own XmlWriter if they wanted more control over the results of the transform or what happened to those results&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;All of this was a great benefit to us in developing the transform engine, but, we ran into one sticky issue (well, one we care about for the purposes of this post, anyhow). The problem was that an xsl transform provides some ways within the xslt language to control how the results are written out.&amp;nbsp; This meant that there were two ways to specify these output options, one in the xslt and one in the WriterSettings passed into an XmlWriter.&amp;nbsp; &lt;BR&gt;For example, if you write the following stylesheet:&lt;BR&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;&lt;FONT size=2&gt;&lt;FONT color=#0000ff&gt;&amp;lt;?&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;xml&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;version&lt;/FONT&gt;=&lt;FONT color=#0000ff&gt;"1.0"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;encoding&lt;/FONT&gt;=&lt;FONT color=#0000ff&gt;"UTF-8"&lt;/FONT&gt; &lt;FONT color=#0000ff&gt;?&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;xsl:stylesheet &lt;FONT color=#ff0000&gt;version&lt;/FONT&gt;="1.0" &lt;FONT color=#ff0000&gt;xmlns:xsl&lt;/FONT&gt;=&lt;FONT color=#0000ff&gt;"http://www.w3.org/1999/XSL/Transform"&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp; &lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;xsl:output &lt;FONT color=#ff0000&gt;method&lt;/FONT&gt;=&lt;FONT color=#0000ff&gt;"xml"&lt;/FONT&gt; &lt;FONT color=#ff0000&gt;indent&lt;/FONT&gt;=&lt;FONT color=#0000ff&gt;"no"&lt;/FONT&gt;&lt;FONT color=#0000ff&gt;/&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp; &lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;xsl:template &lt;FONT color=#ff0000&gt;match&lt;/FONT&gt;=&lt;FONT color=#0000ff&gt;"/"&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#0000ff&gt;&amp;lt;&lt;/FONT&gt;hello&lt;FONT color=#0000ff&gt;/&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&amp;nbsp; &lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;xsl:template&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&lt;FONT color=#0000ff&gt;&amp;lt;/&lt;/FONT&gt;xsl:stylesheet&lt;FONT color=#0000ff&gt;&amp;gt;&lt;/FONT&gt;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/FONT&gt;You would expect to have your output formatted without indenting because you have specified indent="no".&amp;nbsp; Of course, as you can imagine, indented formatting of xml also happens to be useful for cases where you are using an XmlWriter without any xslt involved.&amp;nbsp; For this reason, you will find that the XmlWriterSettings class also has an Indent property.&amp;nbsp; So, what would you expect to be the result from using the above xslt with the following code?&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&lt;FONT color=#008000&gt;XmlWriterSettings&lt;/FONT&gt; settings = new &lt;FONT color=#008000&gt;XmlWriterSettings&lt;/FONT&gt;();&lt;BR&gt;settings.Indent = &lt;FONT color=#0000ff&gt;true&lt;/FONT&gt;;&lt;BR&gt;&lt;FONT color=#008000&gt;XmlWriter&lt;/FONT&gt; writer = &lt;FONT color=#008000&gt;XmlWriter&lt;/FONT&gt;.Create("out.xml", settings);&lt;BR&gt;transform.Transform("test.xml", &lt;FONT color=#0000ff&gt;null&lt;/FONT&gt;, writer);&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;You will get the indenting specified in the WriterSettings (indent=true) rather then what is specified in the xslt (indent="no").&amp;nbsp; Of course, it is neither practical nor desirable to have the user specify the correct settings for each of their stylesheets, so instead the XslCompiledTransform exposes the OutputSettings property.&amp;nbsp; When you call the Load method of the transform, it determines what the correct XmlWriterSettings should look like. In the case that you call one of the Transform() overloads which does not take an XmlWriter, this settings instance will be used to construct a writer on your behalf, but if you are passing in your own writer, then you can either use this instance directly (as you can see above from Oleg's code) or you can Clone() this instance and twiddle whatever particular settings you care about before constructing a writer.&amp;nbsp; &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=443881" width="1" height="1"&gt;</description></item><item><title>Use of GetElementsByTagName considered harmful</title><link>http://blogs.msdn.com/eriksalt/archive/2005/07/20/GetElementsByTagName.aspx</link><pubDate>Wed, 20 Jul 2005 04:58:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:440785</guid><dc:creator>eriksalt</dc:creator><slash:comments>24</slash:comments><comments>http://blogs.msdn.com/eriksalt/comments/440785.aspx</comments><wfw:commentRss>http://blogs.msdn.com/eriksalt/commentrss.aspx?PostID=440785</wfw:commentRss><description>&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;As you may already be aware, there is an &lt;/FONT&gt;&lt;A href="http://msdn.microsoft.com/vstudio/java/compare/xmlperf/default.aspx"&gt;&lt;FONT face=Tahoma size=2&gt;article&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt; on msdn about the great performance improvements we made in the V2 xml stack.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;This is a pretty big event for the team, since increasing performance was one of the big goals of this release.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;While I posted this to give a shout-out to the team for the great perf work in they did for Whidbey, I want to take a minute to point out another interesting part of the article.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Up at the top of this article you will find a this paragraph:&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 8.4pt 0.5in; TEXT-INDENT: -0.25in; mso-margin-top-alt: auto; mso-list: l0 level1 lfo1; tab-stops: list .5in"&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Verdana; mso-fareast-font-family: Verdana; mso-bidi-font-family: Verdana"&gt;&lt;SPAN style="mso-list: Ignore"&gt;2.&lt;SPAN style="FONT: 7pt 'Times New Roman'"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;SPAN style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Verdana"&gt;We also found that Sun is using the GetElementsByTagName method in C#, and this results in a mismatch of the C# and Java versions. Although both harnesses use XmlElement.GetElemensByTagName(), the C# implementation of this method keeps track of a live list of nodes which is&amp;nbsp;negatively impacted&amp;nbsp;by some of the DOM test scenarios that have edits. A better method&amp;nbsp;for element selection in the C# harness is XmlElement.SelectNodes() which matches the Java harness in functionality. &lt;?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /&gt;&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;When I first read this, it caused me some concern.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Were we somehow ‘cheating’ by changing the nature of the test?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Was there something wrong with GetElementsByTagName that I (and the various xml developers out there) should be aware of?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;I did a little digging, and wanted to share the results.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;SPAN lang=EN style="COLOR: black; mso-ansi-language: EN"&gt;&lt;FONT face=Tahoma size=2&gt;The W3C Level1 DOM spec has &lt;/FONT&gt;&lt;A href="http://www.w3.org/TR/1998/REC-DOM-Level-1-19981001/level-one-core.html#ID-1590626202"&gt;&lt;FONT face=Tahoma size=2&gt;this&lt;/FONT&gt;&lt;/A&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt; to say about the results of GetElementsByTagName (I underlined the last sentence for emphasis):&lt;o:p&gt;&lt;/o:p&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt 0.5in"&gt;&lt;SPAN lang=EN style="FONT-SIZE: 8pt; COLOR: black; FONT-FAMILY: Verdana; mso-bidi-font-family: Tahoma; mso-ansi-language: EN"&gt;The DOM also specifies a NodeList interface to handle ordered lists of Nodes, such as the children of a Node, or the elements returned by the Element.getElementsByTagName method, and also a NamedNodeMap interface to handle unordered sets of nodes referenced by their name attribute, such as the attributes of an Element. &lt;U&gt;NodeLists and NamedNodeMaps in the DOM are "live", that is, changes to the underlying document structure are reflected in all relevant NodeLists and NamedNodeMaps&lt;/U&gt;.&lt;o:p&gt;&lt;/o:p&gt;&lt;/SPAN&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In other words, GetElementsByTagName is, according to the spec, supposed to return a ‘live list’ where changes to the underlying DOM are reflected in the returned NodeList.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;The MS implementation of this function conforms to the spec, but the Sun/Java implementation does not. &lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;Unfortunately, this conformance comes at a cost.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;In this case, the cost is a non-trivial hit to the speed and working set of code which uses GetElementsByTagName.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Let me explain why.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;In order to keep the NodeLists returned from GetElementsByTagName live, each list needs to ‘register’ somehow with the related element so that it can be notified when the children of that element change.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When we first implemented this function, we thought about adding a series of events to XmlElement.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;NodeLists could register for these events and react appropriately.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Unfortunately, this turns out to bloat the size of a DOM tree, and the performance costs caused by the related cache misses were unacceptable.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Because of this we moved to a model where only XmlDocument exposed ‘OnChange’ events.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;When an item is added into the DOM, the XmlDocument.NodeInsterted event fires, each NodeList can determine if the new element should be added to its list or not, and then take the appropriate action.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;&lt;/FONT&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma&gt;&lt;FONT size=2&gt;This solution has the advantage that it adds no extra overhead to scenarios which do not call GetElementsByTagName, and the overhead is minimal even for scenarios which do use GetElementsByTagName, as long as those scenarios do not change the DOM (in this case the only overhead is the cost of registering for the event and a small increase in allocated memory for the created delegate).&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;&lt;/FONT&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The real problem shows up when you combine calls to GetElementsByTagName and edits to the DOM.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Imagine that you had a moderate sized DOM (a few hundred elements) and for each element you called GetElementsByTagName, which results in a few hundred NodeLists registering for the XmlDocument.NodeInsterted.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Now, after walking through the tree, you add a few elements.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Each time you add an element, the NodeInserted event fires, and &lt;B style="mso-bidi-font-weight: normal"&gt;hundreds&lt;/B&gt; of delegate functions will get called.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As you can imagine, this can cause quite a hit to the performance of your application.&lt;/FONT&gt;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P class=MsoNormal style="MARGIN: 0in 0in 0pt"&gt;&lt;FONT face=Tahoma size=2&gt;The bottom line?&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;If you are using GetElementsByTagName, especially in scenarios where you edit the DOM, you should investigate using SelectNodes instead.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;SelectNodes takes an XPath expression, but all you would need to do to get back the same elements as what is called by GetElementsByTagName would be to pass in “\\ElementName”&amp;nbsp;&lt;FONT color=#ff0000&gt;[edit:&amp;nbsp;that should read "//ElementName]&lt;/FONT&gt;&amp;nbsp;to SelectNodes where you would have passed “ElementName” in to GetElementsByTagName.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;As always, you should measure how this changes your perf before switching over, especially in cases where you are not editing the DOM, since SelectNodes does a little more work to support the full syntax, but don’t be afraid to try.&lt;SPAN style="mso-spacerun: yes"&gt;&amp;nbsp; &lt;/SPAN&gt;Even if your perf is equivalent in both cases, you may want to look at switching over, since we are very focused on improving XPath performance, so you may find your perf improve over time along with our XPath implementation (note: as always Microsoft’s plans are always subject to change, while we currently are focused on XPath performance, some future change may alter this in the future).&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face=Tahoma size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=440785" width="1" height="1"&gt;</description></item></channel></rss>