2

I am trying to create a XML using XSLT file by exporting from an RDL file via Visual Studio 2008 R2 (BIDS) or SSRS.

The export results in the following xml code

<?xml version="1.0" encoding="utf-8"?>
<Report xsi:schemaLocation="testreport http://reportserver?%2Ftestreport&amp;rs%3AFormat=XML&amp;rc%3ASchema=True" Name="testreport"             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="testreport">
 <ProductList>
  <Details_Collection>
   <Details>
    <ID>602</ID>
    <Title>302</Title>
   </Details>
   <Details>
    <ID>603</ID>
    <Title>303</Title>
   </Details>
  </Details_Collection>
 </ProductList>
</Report> 

From another post here on this site I got the following XSLT code:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    exclude-result-prefixes="xsi">
  <xsl:output method="xml" indent="yes" encoding="utf-8" />

  <!-- rule to suppress the undesired nodes -->
  <xsl:template match="Report|ProductList|Details_Collection">
    <xsl:apply-templates/>
  </xsl:template>

  <!-- rule to rename the Details node -->
  <xsl:template match="Details">
    <item>
      <xsl:apply-templates/>
    </item>
  </xsl:template>

  <!-- rule to copy everything else -->
  <!-- see https://stackoverflow.com/questions/857010/xsl-avoid-exporting-namespace-defintions-to-resulting-xml-documents-->
  <!-- see https://stackoverflow.com/questions/14166259/xslt-default-template-confusion -->
  <xsl:template match="*|@*">
    <xsl:element name="{name()}">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <!-- rule to start the conversion and provide the wrapper tags -->
  <xsl:template match="/">
    <rss version="2.0">
      <channel>
        <xsl:apply-templates/>
      </channel>
    </rss>
  </xsl:template>

</xsl:stylesheet>

When applying the XSLT, the export results in the following XML code

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
    <Report>
      <ProductList>
        <Details_Collection>
          <Details>
            <ID>602</ID>
            <Title>302</Title>
          </Details>
          <Details>
            <ID>603</ID>
            <Title>303</Title>
          </Details> 
        </Details_Collection>
      </ProductList>
    </Report>
  </channel>
</rss>

What am I not seeing here? The "Report", "ProductList","Details_Collection" should not be appearing in the output and the "Detail" Element should be named "item". It seems as if the elements cannot be adressed by their names (the only template matches for elements that seem to be working are "/", "*" and "/*"). I never achieved to adress one specific Element by its name.

I would be expecting something like this:

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
  <channel>
     <item>
         <ID>602</ID>
         <Title>302</Title>
      </item>
      <item>
         <ID>603</ID>
         <Title>303</Title>
      </item> 
  </channel>
</rss>

Can someone help me? Cheers Commx

Community
  • 1
  • 1
commx
  • 21
  • 1
  • 2

1 Answers1

2

Your input XML is in a namespace, that is, a default namespace:

<Report xmlns="testreport">

All descendant elements will also belong to this namespace. What matters in your case is that the element Report and the one called {testreport}Report (the {} tell you that a namespace is present) are entirely different elements.

So, if your template matches

<xsl:template match="Report">

it is only triggered if an element named "Report" is found which is in no namespace. Instead, if you need to address the names of specific elements and if they are in a namespace, you need to declare this namespace in an XSLT stylesheet and prefix those element names:

<xsl:stylesheet xmlns:tst="testreport">
  <xsl:template match="tst:Report">
    <!--...-->
  </xsl:template>
  <!--...-->
</xsl:stylesheet>

You observe that

the only template matches for elements that seem to be working are "/", "*" and "/*"

because those patterns are generic ones that do not make use of specific element names that would need prefixing.

XSLT Stylesheet

More details: No need for redeclaring the xsi namespace in the stylesheet - I have omitted it. Also, some processors keep whitespace nodes which results in the output being badly formatted - I have added xsl:strip-space to account for this.

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:tst="testreport"
    exclude-result-prefixes="tst">
  <xsl:output method="xml" indent="yes" encoding="utf-8" />

  <xsl:strip-space elements="*"/>

  <!-- rule to suppress the undesired nodes -->
  <xsl:template match="tst:Report|tst:ProductList|tst:Details_Collection">
    <xsl:apply-templates/>
  </xsl:template>

  <!-- rule to rename the Details node -->
  <xsl:template match="tst:Details">
    <item>
      <xsl:apply-templates/>
    </item>
  </xsl:template>

  <!-- rule to copy everything else -->
  <xsl:template match="*|@*">
    <xsl:element name="{name()}">
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

  <!-- rule to start the conversion and provide the wrapper tags -->
  <xsl:template match="/">
    <rss version="2.0">
      <channel>
        <xsl:apply-templates/>
      </channel>
    </rss>
  </xsl:template>

</xsl:stylesheet>

XML Output

<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
   <channel>
      <item>
         <ID>602</ID>
         <Title>302</Title>
      </item>
      <item>
         <ID>603</ID>
         <Title>303</Title>
      </item>
   </channel>
</rss>
Mathias Müller
  • 22,203
  • 13
  • 58
  • 75