Best xml questions in January 2011

Is parsing JSON faster than parsing XML

12 votes

I'm creating a sophisticated JavaScript library for working with my company's server side framework.

The server side framework encodes its data to a simple XML format. There's no fancy namespacing or anything like that.

Ideally I'd like to parse all of the data in the browser as JSON. However, if I do this I need to rewrite some of the server side code to also spit out JSON. This is a pain because we have public APIs that I can't easily change.

What I'm really concerned about here is performance in the browser of parsing JSON versus XML. Is there really a big difference to be concerned about? Or should I exclusively go for JSON? Does anyone have any experience or benchmarks in the performance difference between the two?

I realize that most modern web developers would probably opt for JSON and I can see why. However, I really am just interested in performance. If there's a proven massive difference then I'm prepared to spend the extra effort in generating JSON server side for the client.

JSON should be faster since it's JS Object Notation, which means it can be recognized natively by JavaScript. In PHP on the GET side of things, I will often do something like this:

<script type="text/javascript">
    var data = <?php json_encode($data)?>;
</script>

For more information on this, see here:

Why is Everyone Choosing JSON Over XML for jQuery?

Also...what "extra effort" do you really have to put into "generating" JSON? Surely you can't be saying that you'll be manually building the JSON string? Almost every modern server-side language has libraries that convert native variables into JSON strings. For example, PHP's core json_encode function converts an associative array like this:

$data = array('test'=>'val', 'foo'=>'bar');

into

{"test": "val", "foo": "bar"}

Which is simply a JavaScript object (since there are no associative arrays (strictly speaking) in JS).

What are the limits to code generation from XML Schema in C#?

11 votes

I've seen several questions regarding problems with generating classes from XML Schema using xsd.exe, along with suggestions for how to pre-process the schema (often using XSLT) to resolve some of the trickier aspects prior to generation. My question is whether it's possible to construct a C# code generator that is 100% compliant with XML Schema. Are the problems with xsd.exe merely a question of its implementation, or do they point to a fundamental inconsistency between XML Schema and C#?

In particular, I'm interested in how to map concepts in XML Schema to C# - what are the accepted mappings, which mappings are debatable, are there XML Schema constructs that are inherently un-mappable and are there C# constructs that are underutilised? Is there a compliance specification that would provide rules for mapping, such that it could be implemented and tested?

EDIT: For the sake of clarity I'm fully aware that XML Schema won't provide me with fully implemented C# interfaces, I'm interested in whether it can be fully mapped to a C# class hierarchy.

EDIT 2: I've added a small bounty, as I'm interested in getting a bit more detail.

EDIT 3: Bounty still open, but so far heading toward stakx - a good answer but mainly dealing with how to replicate C# structures in XML Schema, rather than the other way round. Good input though.

Interesting question. Not too long ago, I was wondering about exactly the same thing.

I will show a couple examples of how far I got. My demonstration will not be complete (considering that the XML Schema specification is fairly comprehensive), but it should suffice to show...

  • that you can do better than xsd.exe (if you're willing to adhere to certain patterns when you write your XML Schema); and
  • that XML Schema allows type declarations that cannot be expressed in C#. This should not come as a big surprise, considering that XML and C# are very different languages with quite different purposes.

Declaring an interface in XML Schema

C# interfaces can be defined in XML Schema with complex types. For example:

<xsd:complexType name="IFoo" abstract="true">
  <xsd:attribute name="Bar" type="xsd:string" use="required" />
  <xsd:attribute name="Baz" type="xsd:int" use="optional" />
</xsd:complexType>

corresponds fairly well to:

interface IFoo
{
    string Bar { get; set; }
    int?   Baz { get; set; }
}

The pattern here is that abstract and named (non-anonymous) complex types are basically the XML Schema equivalent of interfaces in C#.

Note some problems with the mapping:

  • C# access modifiers such as public, internal etc. cannot be rendered in XML Schema.

  • You have no way of expressing the difference between a C# field and a property in XML Schema.

  • You cannot define methods in XML Schema.

  • You also have no way of expressing the difference between a C# struct and class. (There's simply types in XML Schema, which roughly correspond to .NET value types; but they're much more restricted in XML Schema than complex types.)

  • The usage of usage="optional" can be used to map nullable types. In XML Schema, you could define a string attribute as optional. Crossing over to C#, some loss in translation occurs: Since string is a reference type, it cannot be declared as nullable (since it's already nullable by default).

  • XML Schema also allows usage="prohibited". This is again something that cannot be expressed in C#, or at least in a nice fashion (AFAIK).

  • From my experiments, it appears that xsd.exe will never generate C# interfaces from abstract complex types; it will stay with abstract classes instead. (I'm guessing that this is to keep the translation logic reasonably simple.)

Declaring abstract classes

Abstract classes can be done very similarly to interfaces:

<xsd:element name="FooBase" abstract="true">
  <xsd:complexType>
    ...
  </xsd:complexType>
</xsd:element>

Here, you define an element with the abstract attribute set to true, and embed an anonymous complex type inside it.

This corresponds to the following type declaration in C#:

abstract class FooBase { ... }

Declaring classes

As above, but omit the abstract="true".

Declaring classes that implement an interface

<xsd:complexType name="IFoo" abstract="true">
  ...
</xsd:complexType>

<xsd:element name="Foo" type="IFoo" />

This maps to:

interface IFoo { ... }

class Foo : IFoo { ... }

That is, you define both a named, abstract complex type (the interface), and a named element with that type.

  • Note that the C# code snippet above contains ... twice, while the XML Schema snippet has only one .... How come?

    Because you cannot define methods (code), and because you also cannot specify access modifiers, you don't need to "implement" a complex type with the element in XML Schema. The "implementation" of the complex type would be identical to the original declaration. If the complex type defines some attributes, these simply get mapped to auto-properties in a C# interface implementation.

Expressing inheritance relationships in XML Schema

Class and interface inheritance in XML Schema can be defined through a combination of type extensions and element substitution groups:

<xsd:element name="Base" type="base" />
<xsd:element name="Derived" substitutionGroup="Base" type="derived" />
                       <!-- ^^^^^^^^^^^^^^^^^^^^^^^^ -->

<xsd:complexType name="base">
  <xsd:attribute name="Foo" type="xsd:boolean" use="required" />
</xsd:complexType>

<xsd:complexType name="derived">
  <xsd:complexContent>
    <xsd:extension base="base">  <!-- !!! -->
      <xsd:attribute name="Bar" type="xsd:string" use="required" />
    </xsd:extension>
  </xsd:complexContent>
</xsd:complexType>

This maps to:

class Base
{
    bool Foo { get; set; }
}

class Derived : Base
{
    string Bar { get; set; }
}

Note:

  • We're again using named complex types. But this time, they're not defined abstract="true", since we're not defining any C# interface type.

  • Note the references: Element Derived is in Base's substitution group; at the same time, complex type derived is an extension of complex type base. Derived has type derived, Base has type base.

  • Named complex types that are not abstract have no direct counterpart in C#. They're not classes, since they cannot be instantiated (in XML, elements, not types, have roughly the same function as value constructors in F# or object instantiation in C#); neither are they truly interfaces, since they are not declared abstract.

Some things that I haven't covered in my answer

  • Showing how one would declare, in XML Schema, a C# class type that implements several interfaces.

  • Showing how complex content in XML Schema maps to C# (my first guess it that there's no correspondence in C# at all; at least not in the general case).

  • enums. (They are realised in XML Schema by restricting a simple type via enumeration, btw.)

  • const fields in a class (these would possibly map to attributes with a fixed value).

  • How to map xsd:choice, xsd:sequence to C#; How to correctly map IEnumerable<T>, ICollection<T>, IList<T>, IDictionary<TKey, TValue> to XML Schema?

  • XML Schema simple types, which sound like they're the corresponding concept of .NET value types; but are far more restricted and have a different purpose.

There's many many more things that I haven't shown, but by now you can probably see the basic patterns behind my examples.

To do all this correctly, one would have to systematically go through the XML Schema specification and see how each concept mentioned there maps best to C#. (There's perhaps no single best solution, but several alternatives.) But I explicitly meant to show only a couple of interesting examples. I hope that was still informative enough!

Good Tools To Develop a GUI in Android?

9 votes

I would like to know if there exists a good tool to implement a design in Android like tools to make easy to implement and that can generate XML

Thanks for your help.

Use DroidDraw for better GUI layouts.

Why are Scala XML literals sensitive to whitespace between the tags?

8 votes

I've discovered that Scala XML literals are sensitive to whitespace, which is kinda strange, isn't it? since XML parsers don't normally give a damn about spaces between the tags.

This is a bummer because I'd like to set out my XML neatly in my code:

<sample>
  <hello />
</sample>

but Scala considers this to be a different value to

<sample><hello /></sample>

Proof is in the pudding:

scala> val xml1 = <sample><hello /></sample>
xml1: scala.xml.Elem = <sample><hello></hello></sample>

scala> val xml2 = <sample>
     | <hello />
     | </sample>
xml2: scala.xml.Elem = 
<sample>
<hello></hello>
</sample>

scala> xml1 == <sample><hello /></sample>
res0: Boolean = true

scala> xml1 == xml2
res1: Boolean = false

... What gives?

If you liked it you should have put a trim on it:

scala> val xml1 = <sample><hello /></sample>
xml1: scala.xml.Elem = <sample><hello></hello></sample>

scala> val xml2 = <sample>
     | <hello />
     | </sample>
xml2: scala.xml.Elem = 
<sample>
<hello></hello>
</sample>

scala> xml1 == xml2
res14: Boolean = false

scala> xml.Utility.trim(xml1) == xml.Utility.trim(xml2)
res15: Boolean = true

Reading a *.CSPROJ file in C#

7 votes

I am attempting to write some code to read in a *.CSPROJ file using C#

The code I have is as follows

   XmlDocument xmldoc = new XmlDocument();
   xmldoc.Load(fullPathName);

   XmlNamespaceManager mgr = new XmlNamespaceManager(xmldoc.NameTable);
   //mgr.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");

   foreach (XmlNode item in xmldoc.SelectNodes("//EmbeddedResource") )
   {
      string test = item.InnerText.ToString();
   }

using the debugger I can see that 'fullPathName" has the correct value and the xmldoc once loaded has the correct contents.

The xmldoc does not have any "Nodes" though, as if the contents are not recognised as XML.

Using a XML editor the *.csproj file validates an XML document.

Where am I going wrong?

You were getting close with your XmlNamespaceManager addition, but weren't using it in the SelectNodes method:

XmlNamespaceManager mgr = new XmlNamespaceManager(xmldoc.NameTable);
mgr.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");

foreach (XmlNode item in xmldoc.SelectNodes("//x:ProjectGuid", mgr))
{
    string test = item.InnerText.ToString();
}

(I switched to searching for a different element as my project didn't have any embedded resources)

android import ressources from library project

7 votes

hello, is it possible to use ressources like strings that are defined in library projects in the application-projects? if so, how? because i cant seem to resolve the strings i would like to resolve like this:

String title = "sample";
int id = ressources.getIdentifier(title, "string", "com.package");

gives me this exception

WARN/ResourceType(278): No package identifier when getting value for resource number 0x00000000 WARN/System.err(278): android.content.res.Resources$NotFoundException: String resource ID #0x0

the string ("sample") i am looking for is definitely in this package provided in the strings.xml of the library project. i can even see it in the R.java

So it looks like

int id = ressources.getIdentifier(title, "string", "com.package");

is returning 0, meaning it can't find the specified resource. The subsequent call to ressources.getIdentifer() causes the exception, since 0 is not a valid resource id.

Here are some debug/alternative ideas:


  • You've probably already done this a dozen times, but it doesn't hurt mentioning: first recheck spelling of everything:

    • package spelling is correct (both in library project and in client project),
    • resource string is correct (library project and client project),
    • is library spelling correct in the uses-library element the AndroidManifest.xml,
    • etc.

  • Can you access any resources in that library or is the problem specific to that resource (title) or is it specific to that type of resource(strings)? Can you access the resources of another library?

  • Are you accessing the library as a jar file? You can jar the code, but you can't access resources from a jar.

Android - Is it possible to create a custom library to use across several appilcations?


  • Did you try the alternate name format:

Code

String fullyQualifiedResourceName = "com.package:string/sample";
int id = ressources.getIdentifier(title, null, null);
if (id == 0) {
    Log.e(TAG, "Lookup id for resource '"+fullyQualifiedResourceName+"' failed";
    // graceful error handling code here
}

  • You could try using reflection:

Code

final String resourceName= "sample";
final int id;
try {
    final Class resourceType = com.package.R.string.class;
    final Field field = resourceType.getField(title);
    id = field.getInt(null);
} catch (final Exception e) {
    Log.e(TAG, "Lookup id for resource '"+resourceName+"' failed";
    // graceful error handling code here
}

Android, getting resource ID from string?

http://daniel-codes.blogspot.com/2009/12/dynamically-retrieving-resources-in.html

In C#, is there a way to add an XML node to a file on disk WITHOUT loading it first?

7 votes

Hi, I have a very basic XML structure/file on disk which is something like:

<root>
    <data timestamp="dd-mm-yyyy" type="comment">kdkdkdk</data>
    <data timestamp="dd-mm-yyyy" type="event">kdkdkdkgffgfdgf</data>
    <data timestamp="dd-mm-yyyy" type="something">kddsdsfsdkdkdk</data>
</root>

The XML will be, as mentioned, in an external file on disk. As the file might grow fairly large (actually gets 'trimmed' every couple of weeks), I don't want to load the XML file first to add a new node...

Is there a way to add a new node like this? it can be just added to the top/bottom etc, as the process that actually uses the XML sorts it by timestamp anyway..

I'm guessing a crude way is to append the node as text.. however I think that would add the node AFTER the end tag??

Any ideas gratefully received.. David.

There are a a number of decent answers here already, however just to put another spin on this, are you sure this data needs to be stored as an XML file?

The data you are storing looks fairly simple (i.e a record with three fields, date, type and some string data. If you do not need any of the added benefits that XML provides (http://stackoverflow.com/questions/1820129/when-and-why-is-xml-preferable-to-csv) then why not just use basic CSV? That way you can just keep appending to it just like a log file via File.AppendText("filename").

(Hell, it might even be possible to use something like log4net to manage the logging and any clean up housekeeping.)

Parse XML in Haskell

6 votes

I'm trying to get data from a webpage that serves a XML file periodically with stock market quotes. (here is an example: http://www.bmfbovespa.com.br/Pregao-Online/ExecutaAcaoAjax.asp?CodigoPapel=VALE3 )

The structure of the XML is very simple, and is something like this:

<?xml version="1.0"?>
<Contents>
  <StockQuote Symbol="PETR3" Date="21-12-2010" Time="13:20" Price="23.02" />
</Contents>

(it's more than that but this suffices as an example).

I'd like to parse it to a data structure:

 data Quote = Quote { symbol :: String, 
                      date   :: Data.Time.Calendar.Day, 
                      time   :: Data.Time.LocalTime.TimeOfDay,
                      price  :: Float}

I understand more or less how Parsec works (on the level of the Real World Haskell book), and I tried a bit the Text.XML library but all I could develop was a code that worked but is too big for such a simple task and looks like a half baked hack and not the best one could do.

I don't know a lot about parsers and XML (I know basically what I read in the RWH book, I never used parsers before) (I just do statistical and numerical programming, I'm not a computer scientist). Is there a XML parsing library where I could just tell what is the model and extract the information right away, without having to parse each element by hand and without having to parse pure string?

I'm thinking about something like:

  myParser = do cont  <- openXMLElem "Contents"
                quote <- openXMLElem "StockQuote" 
                symb <- getXMLElemField "Symbol"
                date <- getXMLElemField "Date"
                (...) 
                closequote <- closeXMLElem "StockQuote"
                closecont  <- closeXMLElem "Contents"
                return (symb, date)


  results = parse myParser "" myXMLString

where I wouldn't have to deal with the pure string and create the combinators myself (I suck at it).

EDIT: I probably need to read a bit (just enough to get this done the right way) about parsers in general (not only Parsec) and the minimum about XML. Do you guys recomend something?

The real string I have to parse is this:

 stringTest = "<?xml version=\"1.0\"?>\r\n<ComportamentoPapeis><Papel Codigo=\"PETR3\" 
 Nome=\"PETROBRAS ON\" Ibovespa=\"#\" Data=\"05/01/201100:00:00\" 
 Abertura=\"29,80\" Minimo=\"30,31\" Maximo=\"30,67\" Medio=\"30,36\" 
 Ultimo=\"30,45\" Oscilacao=\"1,89\" Minino=\"29,71\"/></ComportamentoPapeis>\r\n"

EDIT2:

I tried the following (readFloat, readQuoteTime, etc... are just functions to read things from strings).

bvspaParser :: (ArrowXml a) => a XmlTree Quote
bvspaParser = hasName "ComportamentoPapeis" /> hasName "Papel" >>> proc x -> do
   (hour,date) <- readQuoteTime ^<< getAttrValue "Data" -< x
   quoteCode   <- getAttrValue "Codigo" -< x
   openPrice   <- readFloat ^<< getAttrValue "Abertura" -< x
   minim       <- readFloat ^<< getAttrValue "Minimo" -< x
   maxim       <- readFloat ^<< getAttrValue "Maximo" -< x
   ultimo      <- readFloat ^<< getAttrValue "Ultimo" -< x
   returnA     -< Quote quoteCode (LocalTime date hour) openPrice minim maxim ultimo

docParser :: String -> IO [Quote]
docParser  str = runX $ readString [] str >>> (parseXmlDocument False) >>> bvspaParser

When I call it in ghci:

*Main> docParser stringTest >>= print
[]

Is anything wrong?

I've used Haskell XML Toolbox in the past. Something along the lines of

{-# LANGUAGE Arrows #-}

quoteParser :: (ArrowXml a) => a XmlTree Quote
quoteParser =
    hasName "Contents" /> hasName "StockQuote" >>> proc x -> do
    symbol <- getAttrValue "Symbol" -< x
    date <- readTime defaultTimeLocale "%d-%m-%Y" ^<< getAttrValue "Date" -< x
    time <- readTime defaultTimeLocale "%H:%M" ^<< getAttrValue "Time" -< x
    price <- read ^<< getAttrValue "Price" -< x
    returnA -< Quote symbol date time price

parseQuoteDocument :: String -> IO (Maybe Quote)
parseQuoteDocument xml =
    liftM listToMaybe . runX . single $
    readString [] xml >>> getChildren >>> quoteParser

semantic way of representing lines of a play in HTML

6 votes

Take the most famous group of lines of them all:

Hamlet: To be, or not to be: that is
the question: Whether 'tis nobler in
the mind to suffer The slings and
arrows of outrageous fortune, Or to
take arms against a sea of troubles,
And by opposing end them? To die: to
sleep; No more; and by a sleep to say
we end The heart-ache and the thousand
natural shocks That flesh is heir to,
'tis a consummation Devoutly to be
wish'd. To die, to sleep; To sleep:
perchance to dream: ay, there's the
rub; For in that sleep of death what
dreams may come

How would you mark that up in a semantic way, preserving space for a) line number (e.g., 1.1.1), b) character name, and c) of course, the text?

I'm going to have to disappoint you there, but it is not possible. See this A List Apart article for more information.

To summarise, because HTML is a markup language designed specifically to mark up a certain type of document, not all documents can be represented with HTML's limited set of elements:

Some documents cannot be published using HTML. In many cases, we shouldn’t even bother trying. In other cases, we have to radically change the appearance and structure of the document.

They even used a screenplay as an example of one such document. I will recommend you to read the entire article in full to see the rationale, as well other methods for marking up documents.

C# XPath help - Expression not working

6 votes

Here is an example XML doc that matches the one I am getting info from:

<?xml version="1.0" standalone="yes"?>
<Products xmlns="http://tempuri.org/Products.xsd">
  <Movies>
    <Title>Title1</Title>
    <Language>English</Language>
  </Movies>
  <Movies>
    <Title>Title2</Title>
    <Language>English</Language>
  </Movies>
  <Movies>
    <Title>Title3</Title>
    <Language>French</Language>
  </Movies>
  <Books>
    <Title>BTitle1</Title>
    <Genre>Suspense</Genre>
  </Books>
  <Books>
    <Title>BTitle2</Title>
    <Genre>Suspense</Genre>
  </Books>
  <Books>
    <Title>BTitle3</Title>
    <Genre>SciFi</Genre>
  </Books>
  <Books>
    <Title>BTitle4</Title>
    <Genre>SciFi</Genre>
  </Books>
</Products>

Here is my code to get all books with the genre of Suspense:

//Get state list using XPath
XPathDocument xDoc = new XPathDocument(xmlPath); //Path to my file
XPathNavigator xNav = xDoc.CreateNavigator();
string booksQuery = "Books[Genre = \"Suspense\"]";
XPathNodeIterator xIter = xNav.Select(booksQuery);

while (xIter.MoveNext())
{
    //do stuff with xIter.Current
}

I have tried several queries including Products/Books[Genre = \"Suspense\"], Products/Books, ./Books, and Books. My xIter always has zero items.

I'm new to XPath, so I'm sure it's a really simple error, but maybe not. I know I can get a DataSet with the tables [Movies] and [Books] out of this XML file using myDataSet.ReadXml(myXmlPathString); so the XML file is not corrupt. If that helps any.

So, my question ... what am I doing wrong?

XPathDocument xDoc = new XPathDocument(xmlPath); //Path to my file
XPathNavigator xNav = xDoc.CreateNavigator();
XmlNamespaceManager mngr = new XmlNamespaceManager(xNav.NameTable);
mngr.AddNamespace("p", "http://tempuri.org/Products.xsd");
string booksQuery = "//p:Books[p:Genre = \"Suspense\"]";
XPathNodeIterator xIter = xNav.Select(booksQuery,mngr);

Generate/get xpath from XML node java

6 votes

I'm interested in advice/pseudocode code/explanation rather than actual implementation.

  • I'd like to go trough xml document, all of its nodes
  • Check the node for attribute existence

Case if node doesn't have attribute, get/generate String with value of its xpath
Case if node does have attributes, iterate trough attribute list and create xpath for each attribute including the node as well.

Word of advice? Hopefully you will provide some useful intel

EDIT:

Reason for doing this is .. I'm writing automated tests in jmeter, so for every request I need to verify that request actually did its job so I'm asserting results by getting nodes values with xpath.(extra info - irrelevant)

When the request is small its not problem to create asserts by hand, but for larger ones its a really pain in the .. (extra info - irrelevant)

BOUNTY :

I'm looking for java approach

Goal

My goal is to achieve following from this ex xml file :

<root>
    <elemA>one</elemA>
    <elemA attribute1='first' attribute2='second'>two</elemA>
    <elemB>three</elemB>
    <elemA>four</elemA>
    <elemC>
        <elemB>five</elemB>
    </elemC>
</root>

to produce the following :

//root[1]/elemA[1]='one'
//root[1]/elemA[2]='two'
//root[1]/elemA[2][@attribute1='first']
//root[1]/elemA[2][@attribute2='second']
//root[1]/elemB[1]='three'
//root[1]/elemA[3]='four'
//root[1]/elemC[1]/elemB[1]='five'

Explained :

  • If node value/text is not null/zero, get xpath , add = 'nodevalue' for assertion purpose
  • If node has attributes create assert for them too

BOUNTY UPDATE :

I found this example, it doesn't produce the correct results , but I'm looking something like this:

http://www.coderanch.com/how-to/java/SAXCreateXPath

BOUNTY UPDATE II:

Looking at Dimitre Novatchev answer, the output is correct for the case provided in my question, however I discovered one case which I didn't mention in my question and its xpath is not being displayed the case is :

<root>
    <elemX serial="kefw90234kf2esda9231">
        <id>89734</id>          
       </elemX>
   </root>

This produces :

//root/elemX/id='89734'

Instead :

//root/elemX[@serial='kefw90234kf2esda9231']
//root/elemX/id='89734'

Update:

@c0mrade has updated his question. Here is a solution to it:

This XSLT transformation:

<xsl:stylesheet version="1.0"  xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:variable name="vApos">'</xsl:variable>

    <xsl:template match="*[@* or not(*)] ">
      <xsl:if test="not(*)">
         <xsl:apply-templates select="ancestor-or-self::*" mode="path"/>
         <xsl:value-of select="concat('=',$vApos,.,$vApos)"/>
         <xsl:text>&#xA;</xsl:text>
        </xsl:if>
        <xsl:apply-templates select="@*|*"/>
    </xsl:template>

    <xsl:template match="*" mode="path">
        <xsl:value-of select="concat('/',name())"/>
        <xsl:variable name="vnumPrecSiblings" select=
         "count(preceding-sibling::*[name()=name(current())])"/>
        <xsl:if test="$vnumPrecSiblings">
            <xsl:value-of select="concat('[', $vnumPrecSiblings +1, ']')"/>
        </xsl:if>
    </xsl:template>

    <xsl:template match="@*">
        <xsl:apply-templates select="../ancestor-or-self::*" mode="path"/>
        <xsl:value-of select="concat('[@',name(), '=',$vApos,.,$vApos,']')"/>
        <xsl:text>&#xA;</xsl:text>
    </xsl:template>
</xsl:stylesheet>

when applied on the provided XML document:

<root>
    <elemA>one</elemA>
    <elemA attribute1='first' attribute2='second'>two</elemA>
    <elemB>three</elemB>
    <elemA>four</elemA>
    <elemC>
        <elemB>five</elemB>
    </elemC>
</root>

produces exactly the wanted, correct result:

/root/elemA='one'
/root/elemA[2]='two'
/root/elemA[2][@attribute1='first']
/root/elemA[2][@attribute2='second']
/root/elemB='three'
/root/elemA[3]='four'
/root/elemC/elemB='five'

When applied to the newly-provided document by @c0mrade:

<root>
    <elemX serial="kefw90234kf2esda9231">
        <id>89734</id>
    </elemX>
</root>

again the correct result is produced:

/root/elemX='89734'
/root/elemX[@serial='kefw90234kf2esda9231']

Explanation:

  • Only elements that have no children elements, or have attributes are matched and processed.

  • For any such element, if it doesn't have children-elements all of its ancestor-or self elements are processed in a specific mode, named 'path'. Then the "='theValue'" part is output and then a NL character.

  • All attributes of the matched element are then processed.

  • Then finally, templates are applied to all children-elements.

  • Processing an element in the 'path' mode is simple: A / character and the name of the element are output. Then, if there are preceding siblings with the same name, a "[numPrecSiblings+1]` part is output.

  • Processing of attributes is simple: First all ancestor-or-self:: elements of its parent are processed in 'path' mode, then the [attrName=attrValue] part is output, followed by a NL character.

Do note:

  • Names that are in a namespace are displayed without any problem and in their initial readable form.

  • To aid readability, an index of [1] is never displayed.


Below is my initial answer (may be ignored)

Here is a pure XSLT 1.0 solution:

Below is a sample xml document and a stylesheet that takes a node-set parameter and produces one valid XPath expression for every member-node.

stylesheet (buildPath.xsl):


<xsl:stylesheet version='1.0'
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
>

<xsl:output method="text"/>
<xsl:variable name="theParmNodes" select="//namespace::*[local-name() =
'myNamespace']"/>
<xsl:template match="/">
  <xsl:variable name="theResult">
    <xsl:for-each select="$theParmNodes">
    <xsl:variable name="theNode" select="."/>
    <xsl:for-each select="$theNode |
$theNode/ancestor-or-self::node()[..]">
      <xsl:element name="slash">/</xsl:element>
      <xsl:choose>
        <xsl:when test="self::*">           
          <xsl:element name="nodeName">
            <xsl:value-of select="name()"/>
            <xsl:variable name="thisPosition" 
                select="count(preceding-sibling::*[name(current()) = 
                        name()])"/>
            <xsl:variable name="numFollowing" 
                select="count(following-sibling::*[name(current()) = 
                        name()])"/>
            <xsl:if test="$thisPosition + $numFollowing > 0">
              <xsl:value-of select="concat('[', $thisPosition +
                                                           1, ']')"/>
            </xsl:if>
          </xsl:element>
        </xsl:when>
        <xsl:otherwise> <!-- This node is not an element -->
          <xsl:choose>
            <xsl:when test="count(. | ../@*) = count(../@*)">   
            <!-- Attribute -->
              <xsl:element name="nodeName">
                <xsl:value-of select="concat('@',name())"/>
              </xsl:element>
            </xsl:when>     
            <xsl:when test="self::text()">  <!-- Text -->
              <xsl:element name="nodeName">
                <xsl:value-of select="'text()'"/>
                <xsl:variable name="thisPosition" 
                          select="count(preceding-sibling::text())"/>
                <xsl:variable name="numFollowing" 
                          select="count(following-sibling::text())"/>
                <xsl:if test="$thisPosition + $numFollowing > 0">
                  <xsl:value-of select="concat('[', $thisPosition + 
                                                           1, ']')"/>
                </xsl:if>
              </xsl:element>
            </xsl:when>     
            <xsl:when test="self::processing-instruction()">
            <!-- Processing Instruction -->
              <xsl:element name="nodeName">
                <xsl:value-of select="'processing-instruction()'"/>
                <xsl:variable name="thisPosition" 
                   select="count(preceding-sibling::processing-instruction())"/>
                <xsl:variable name="numFollowing" 
                    select="count(following-sibling::processing-instruction())"/>
                <xsl:if test="$thisPosition + $numFollowing > 0">
                  <xsl:value-of select="concat('[', $thisPosition + 
                                                            1, ']')"/>
                </xsl:if>
              </xsl:element>
            </xsl:when>     
            <xsl:when test="self::comment()">   <!-- Comment -->
              <xsl:element name="nodeName">
                <xsl:value-of select="'comment()'"/>
                <xsl:variable name="thisPosition" 
                         select="count(preceding-sibling::comment())"/>
                <xsl:variable name="numFollowing" 
                         select="count(following-sibling::comment())"/>
                <xsl:if test="$thisPosition + $numFollowing > 0">
                  <xsl:value-of select="concat('[', $thisPosition + 
                                                            1, ']')"/>
                </xsl:if>
              </xsl:element>
            </xsl:when>     
            <!-- Namespace: -->
            <xsl:when test="count(. | ../namespace::*) = 
                                               count(../namespace::*)">

              <xsl:variable name="apos">'</xsl:variable>
              <xsl:element name="nodeName">
                <xsl:value-of select="concat('namespace::*', 
                '[local-name() = ', $apos, local-name(), $apos, ']')"/>

              </xsl:element>
            </xsl:when>     
          </xsl:choose>
        </xsl:otherwise>            
      </xsl:choose>
    </xsl:for-each>
    <xsl:text>&#xA;</xsl:text>
  </xsl:for-each>
 </xsl:variable>
 <xsl:value-of select="msxsl:node-set($theResult)"/>
</xsl:template>
</xsl:stylesheet>

xml source (buildPath.xml):


<!-- top level Comment -->
<root>
    <nodeA>textA</nodeA>
 <nodeA id="nodeA-2">
  <?myProc ?>
        xxxxxxxx
  <nodeB/>
        <nodeB xmlns:myNamespace="myTestNamespace">
  <!-- Comment within /root/nodeA[2]/nodeB[2] -->
   <nodeC/>
  <!-- 2nd Comment within /root/nodeA[2]/nodeB[2] -->
        </nodeB>
        yyyyyyy
  <nodeB/>
  <?myProc2 ?>
    </nodeA>
</root>
<!-- top level Comment -->

Result:

/root/nodeA[2]/nodeB[2]/namespace::*[local-name() = 'myNamespace']
/root/nodeA[2]/nodeB[2]/nodeC/namespace::*[local-name() =
'myNamespace']

Avoid reloading all XML data for each repeater - vb.net

6 votes

I am trying to place a repeater within a repeater using xml data. I have it working exactly as I want, but the method I have used reloads the data for each repeater. I think I need to cast as an XmlNode but I'll be honest - I have no idea where to start.

Here is my code - I'd like to keep everything in the code behind if possible.

<script runat="server">

Public doc As New XmlDocument()

Public Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs)

    If Not Page.IsPostBack then

        doc.Load(Server.MapPath("~/myxml/bookstore.xml"))

        Dim nodes As XmlNodeList = doc.SelectNodes("Bookings/Booking[@CLIENT_NO='SA33762']")
        rpMyRepeater.DataSource = nodes
        rpMyRepeater.DataBind()

    End If

End Sub

   Protected Sub itemDB(ByVal s As Object, ByVal e As RepeaterItemEventArgs)
      If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then

         Dim rpt As Repeater = CType(e.Item.FindControl("books"), Repeater)

         If Not (rpt Is Nothing) Then

            doc.Load(Server.MapPath("~/myxml/bookstore.xml"))

            Dim nodes2 As XmlNodeList = doc.SelectNodes("Bookings/Booking[@CLIENT_NO='SA33762']/Products/Book")

            rpt.DataSource = nodes2
            rpt.DataBind()

         End If

      End If
   End Sub

</script>

Any ideas?

Am I missing something here?

Can't you simply comment/remove your doc.Load(Server.MapPath("~/myxml/bookstore.xml")) out within your itemDB Sub? Since you defined doc "globally" and already loaded it on page load? (by doing that you will already avoid reloading the xml)

That said, I do agree with Caspar that you should rather use the XmlDatasource (especially for its caching abilities), you don't have to use the XmlDatasource within your markup - you can always define it within your code-behind as well - Since you're concerned about people seeing your (asp.net server-side based) markup for some reason...

e.g.

Public Sub Page_Load(ByVal Sender As Object, ByVal E As EventArgs) Handles Me.Load

    If Not Page.IsPostBack Then
        Dim source As New XmlDataSource()
        source.DataFile = "~/myxml/bookstore.xml"
        source.XPath = "Bookings/Booking[@CLIENT_NO='SA33762']"
        rpMyRepeater.DataSource = source
        rpMyRepeater.DataBind()
    End If

End Sub

Markup: (Nice thing you'll notice here, is that we bind the second repeater using the source from the first repeater)

<asp:Repeater ID="rpMyRepeater" runat="server">
    <ItemTemplate>
        <%#XPath("//Booking/NAME/text()")%>
        <asp:Repeater runat="server" ID='books' DataSource='<%#XPathSelect("//Booking/Products/Book") %>'>
            <HeaderTemplate>
                <h2>
                    Books</h2>
            </HeaderTemplate>
            <ItemTemplate>
                <p>
                    Title:
                    <%#XPath("TITLE/text()")%></p>
                <p>
                    <%#XPath("BOOKCODE/text()")%></p>
            </ItemTemplate>
        </asp:Repeater>
    </ItemTemplate>
</asp:Repeater>

XML

<?xml version="1.0" encoding="utf-8" ?>
<Bookings>
  <Booking CLIENT_NO="SA33762">
    <NAME>Mr Pf_Test_15033</NAME>
    <Products>
      <Book>
        <TITLE>My Book</TITLE>
        <BOOKCODE>12345</BOOKCODE>
      </Book>
      <Book>
        <TITLE>My Book2</TITLE>
        <BOOKCODE>123456</BOOKCODE>
      </Book>
    </Products>
  </Booking>
</Bookings>

The implementation using the ListView control (one of my favorite asp.net control) will look something like this: (If there's no books available, it will display the markup within the EmptyDataTemplate)

<asp:Repeater ID="rpMyRepeater" runat="server">
    <ItemTemplate>
        <%#XPath("//Booking/NAME/text()")%>
        <asp:ListView runat="server" ID="books" ItemPlaceholderID="phItems" DataSource='<%#XPathSelect("//Booking/Products/Book") %>'>
            <LayoutTemplate>
                <h2>
                    Books</h2>
                <asp:PlaceHolder runat="server" ID="phItems"></asp:PlaceHolder>
            </LayoutTemplate>
            <ItemTemplate>
                <p>
                    Title:
                    <%#XPath("TITLE/text()")%></p>
                <p>
                    <%#XPath("BOOKCODE/text()")%></p>
            </ItemTemplate>
            <EmptyDataTemplate>
                <p>
                    Sorry no books available</p>
            </EmptyDataTemplate>
        </asp:ListView>
    </ItemTemplate>
</asp:Repeater>

Xml Serialization in C#

5 votes

Hi,

I'm trying to follow a microsoft tutorial about XML serialization, but I getting some problems!!

This is XML file, used as input:

<?xml version="1.0" encoding="utf-8"?>
<Books xmlns:books="http://www.cpandl.com" xmlns:money="http://www.cohowinery.com">
  <money:Book>
    <books:TITLE>A Book Title</books:TITLE>
    <money:PRICE books:currency="US Dollar">
      <money:price>9.95</money:price>
    </money:PRICE>
  </money:Book>
</Books>

This is the class to bind the XML:

public class OrderedItem
{
        [XmlElement(Namespace = "http://www.cpandl.com")]
        public string ItemName;
        [XmlElement(Namespace = "http://www.cpandl.com")]
        public string Description;
        [XmlElement(Namespace = "http://www.cohowinery.com")]
        public decimal UnitPrice;
        [XmlElement(Namespace = "http://www.cpandl.com")]
        public int Quantity;
        [XmlElement(Namespace = "http://www.cohowinery.com")]
        public decimal LineTotal;
        // A custom method used to calculate price per item.
        public void Calculate()
        {
            LineTotal = UnitPrice * Quantity;
        }
    }

This function read the XML into 'OrderedItem' class:

Console.WriteLine("Reading with Stream");

// Create an instance of the XmlSerializer.
var serializer = new XmlSerializer(typeof(OrderedItem));

// Reading the XML document requires a FileStream.
Stream reader = new FileStream(filename, FileMode.Open);

// Declare an object variable of the type to be deserialized.
// Call the Deserialize method to restore the object's state.
var i = (OrderedItem)serializer.Deserialize(reader);

Console.SetOut(new StreamWriter("a_output.xml"));
serializer.Serialize(Console.Out, i);

This is the XML after read and rewritten:

<?xml version="1.0" encoding="utf-8"?>
<OrderedItem xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ItemName xmlns="http://www.cpandl.com">Widget</ItemName>
  <Description xmlns="http://www.cpandl.com">Regular Widget</Description>
  <UnitPrice xmlns="http://www.cohowinery.com">2.3</UnitPrice>
  <Quantity xmlns="http://www.cpandl.com">10</Quantity>
  <LineTotal xmlns="http://www.cohowinery.com">23</LineTotal>
</OrderedItem>

As you can see, the namespace are expanded. How should I write the output, to obtain the same XML with namespace label, instead of uri?

You may want to have a look on the overloaded method for serializing an object:

default serialization

defining namespaces for serialization

As mentioned there, you can define XmlSerializerNamespaces with the following code lines:

    // Create an XmlSerializerNamespaces object.
    XmlSerializerNamespaces ns = new XmlSerializerNamespaces();

    // Add two prefix-namespace pairs.
    ns.Add("inventory", "http://www.cpandl.com");
    ns.Add("money", "http://www.cohowinery.com");

Hope that helps.

core animation xml or json framework

5 votes

Does anyone know if there is a framework for dynamically loading core animation sequences from some kind of description file like xml or json or even better if there is some kind of core animation studio. I would need some way to allow designers to work on animations without having to talk to programmers for every single change ...

In a project I worked on, we did this exact thing (at least the description part). The animation data is passed down in JSON and parsed and interpreted. It maps to a lot of the major animation capabilities provided by Core Animation--mostly position and frame animations.

Unfortunately what we developed is proprietary and it is highly doubtful the company would be willing to release it as open source.

In the end my answer to your question is there don't appear to be any frameworks that currently support this, however, implementing it yourself wouldn't be too terribly difficult. Then creating a tool your designers can use to generate the animation JSON would be the next logical step. If the tool was not WYSIWYG but rather just a bit of a pseudo design tool, it probably wouldn't be too hard to create either.

Good luck and best regards.

Validate an XSD schema using XSD

5 votes

Since an XSD schema is a valid XML document itself, is there any main XSD document that could be used to validate any other XSD document?

In case you wonder why I need this, I am working with a program called B2B Data Transformation from Informatica and I am trying to programatically generate an xml document (which is in fact XSD) but the program requires an XSD document that can validate the generated xml.

Yes. XML Schema is written in XML Schema itself and can be downloaded from here

Is this the fastest way to parse my XML into JavaScript objects using jQuery?

4 votes

I have an XML file like this:

<content>
    <box>
        <var1>A1</var1>
        <var2>B1</var2>
        <var3>C1</var3>
        <var4>D1</var4>
    </box>
    <box>
        <var1>A2</var1>
        <var2>B2</var2>
        <var3>C2</var3>
        <var4>D2</var4>
    </box>
    <box>
        <var1>A3</var1>
        <var2>B3</var2>
        <var3>C3</var3>
        <var4>D3</var4>
    </box>
</content>

It has 500 box elements which I need to parse into JavaScript objects. I am using this code which works fine but I am a newbie and maybe I am missing something and would like to get suggestions if there is a better/faster way to do it:

var app = {
    //...
    box: [],

    init: function (file) {
        var that = this;

        $.ajax({
            type: "GET",
            url: file,
            dataType: "xml",
            success: function (xml) {
                $("box", xml).each(function (i) {
                    var e = $(this);
                    that.box[i] = new Box(i, {
                        var1: e.children("var1").text(),
                        var2: e.children("var2").text(),
                        var3: e.children("var3").text(),
                        var4: e.children("var4").text()
                    });
                });
            }
        });
    },
    //...
};

Thanks in advance.

Use JSON if at all possible. That way the browser will do the parsing for you and you won't have to do any post-processing.

JSON from the server

{"content":
  {"box": [
    {"var1": "A1",
     "var2": "B1",
     "var3": "C1",
     "var4": "D1"},
    {"var1": "A2",
     "var2": "B2",
     "var3": "C2",
     "var4": "D2"},
    {"var1": "A3",
     "var2": "B3",
     "var3": "C3",
     "var4": "D3"}]}}

Client JavaScript

var app = {
    //...
    box: [],

    init: function (file) {
        var that = this;

        $.ajax({
            type: "GET",
            url: file,
            dataType: "json",
            success: function(result) {
              that.box = $.map(result.content.box, function(box, i) {
                return new Box(i, box);
              });
            }
        });
    },
    //...
};