tags:

views:

2032

answers:

3

I'm trying to convert some Xaml to HTML using the .NET XslCompiledTransform and am running into difficulties getting the xslt to match Xaml tags. For instance with this Xaml input:

<FlowDocument PagePadding="5,0,5,0" AllowDrop="True" NumberSubstitution.CultureSource="User" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&gt;
  <Paragraph>a</Paragraph>
</FlowDocument>

And this xslt:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl"
>

  <xsl:output method="html" indent="yes"/>

  <xsl:template match="/">
    <html>
      <body>
        <xsl:apply-templates />
      </body>
    </html>
  </xsl:template>

  <xsl:template match="FlowDocument">
    <xsl:apply-templates />
  </xsl:template>

  <xsl:template match="Paragraph" >
    <p>
      <xsl:apply-templates />
    </p>
  </xsl:template>

I get this output:

<html>
    <body>
  a
</body>
</html>

Rather than the expected:

<html>
   <body>
      <p>a</p>
   </body>
</html>

Could this be a problem with the namespace? This is my first attempt at an xsl transform, so I'm at a loss.

+5  A: 

Yes, it's a problem with the namespace. All of the elements in your input document are in the namespace http://schemas.microsoft.com/winfx/2006/xaml/presentation. Your template is trying to match elements that are in the default namespace, and it's not finding any.

You need to declare this namespace in your transform, assign it a prefix, and then use that prefix in any patterns that are intended to match elements in that namespace. So your XSLT should look something like this:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:msxsl="urn:schemas-microsoft-com:xslt" 
    xmlns:p="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    exclude-result-prefixes="msxsl"/>

<xsl:output method="html" indent="yes"/>

<xsl:template match="/">
  <html>
    <body>
      <xsl:apply-templates />
    </body>
  </html>
</xsl:template>

<xsl:template match="p:FlowDocument">
  <xsl:apply-templates />
</xsl:template>

<xsl:template match="p:Paragraph" >
  <p>
    <xsl:apply-templates />
  </p>
</xsl:template>
Robert Rossney
Thanks Robert - I had tried adding the namespace to the xsl:stylesheet tag but hadn't prepended the namespace to the match field.
dmo
A: 

It works when I remove this from your source document:

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

I don't believe your last two templates are matching at all. (You can test by putting something like a wrapping <div> in your FlowDocument template.)

Pistos
The FlowDocument comes directly from a WPF RichTextBox, so I'd rather handle it in the xslt than by manipulating the source. Adding the namespace and qualifying the element match fields fixed the issue.
dmo
A: 

Just try changing

"xsl:template match='/'"

tag in your xsl file with

"xsl:template match='*'"

This should give you the desired output.

Somesh