2009-07-27 13 views
5

Chcę przetłumaczyć plik XML z danymi, jak następuje:XSLT na SSRS zgłosić

<FlatData> 
    <Details1_Collection> 
     <Details1 Customer1="Customer" Total1="3" /> 
     ... 
    </Details1_Collection> 
</FlatData> 

Dane Jestem zainteresowany jest atrybuty i ich wartości w każdym Details1. Problem polega na tym, że te atrybuty niekoniecznie będzie taka sama w każdym pliku XML chcę tłumaczyć, a ja chcę XSL ogólnego przeznaczenia, który mógłby obsłużyć taką Details1 jak te:

<Details1 Customer1="Customer" Total1="3" /> 
<Details1 Name="Jim" Age="14" Weight="180" /> 
<Details1 Date="2009-07-27" Range="1-5" Option1="True" /> 

Te różne Details1 nie będzie występują w tym samym źródłowym pliku XML, ale w różnych plikach. Jednak chciałbym użyć tego samego XSL na każdym z nich.

Myślałem, że potrzebuję czegoś takiego jak <xsl:value-of select="@attribute_name"/>, ale co mam umieścić na @attribute_name, kiedy nie wiem wcześniej, jakie to będą atrybuty? W jaki sposób przechwycić nazwę atrybutu? Chciałbym eksplodować XML źródłowego powyżej coś jak:

<Details1> 
    <Customer1>Customer</Customer1> 
    <Total1>3</Total1> 
</Details1> 

EDIT: dzięki za odpowiedzi! Mam problemy z dostaniem się więcej niż do następnego wyjścia, jednakże:

<?xml version="1.0" encoding="UTF-8"?> 
<FlatData> 
<Details1_Collection></Details1_Collection> 
</FlatData> 

Próbowałem zarówno Lavinio-tych i odpowiedzi Jörn Horstmann użytkownika, jak również próbuje połączyć dwa. Uruchomić polecenie:

msxsl.exe -o output.xml input.xml transform.xsl 

myślę coś, co robi się w drodze jest namespace w pliku wejściowego:

<Report Name="MyReport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="MyReport"> 

Odpowiedz

4

Wystąpił zwiększony poziom trudności z powodu przestrzeni nazw Microsoft SQL Reporting Services 2008, która była częścią wejściowego pliku XML. Z początku nie zdawałem sobie sprawy, że tak ważna jest linia <Report Name="MyReport" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="MyReport">. Podziękowania dla Pavela Minaeva za namespace comment. Poniższy XSL pracował, aby wyodrębnić dane chciałem:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="EXQC005"> 
    <xsl:output method="xml" indent="yes" encoding="utf-8"/> 

    <xsl:template match="/"> 
    <xsl:for-each select="a:Report/a:FlatData/a:Details1_Collection/a:Details1"> 
     <xsl:element name="{name(.)}"> 
     <xsl:for-each select="@*"> 
      <xsl:element name="{name(.)}"> 
      <xsl:value-of select="."/> 
      </xsl:element> 
     </xsl:for-each> 
     </xsl:element> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

myślę postaram się to posprzątać używać apply-templates styl lavinio sugerowane. Dziękuje również Jörn Horstmann za kodw pętlach for-each. Byłoby interesujące dowiedzieć się, dlaczego raporty usług Reporting Services są początkowo po cenach dumpingowych z wartością xmlns ustawioną na nazwę raportu, a nie schema URL.

Będę aktualizować tę odpowiedź, gdy będę precyzować ten XSL.

Edit: oto wersja namespace-agnostyk, gdyż dla każdego raportu innym z Reporting Services, nie będzie widocznie być inna przestrzeń nazw:

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes" encoding="utf-8"/> 

    <xsl:template match="/"> 
    <xsl:for-each select="*[local-name()='Report']/*[local-name()='FlatData']/*[local-name()='Details1_Collection']/*[local-name()='Details1']"> 
     <Details> 
     <xsl:for-each select="@*"> 
      <xsl:element name="{name(.)}"> 
      <xsl:value-of select="."/> 
      </xsl:element> 
     </xsl:for-each> 
     </Details> 
    </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 
3

Można wykorzystać "@*" odnieść się do wszystkich atrybutów, jak te przykłady:

  • <xsl:value-of select="@*"/>
  • <xsl:apply-templates select="@*"/>
  • <xsl:template match="@*">

<xsl:element name=""> konstrukt może być wykorzystane do stworzenia nowego elementu z dowolną nazwą oraz funkcje name() lub local-name() powróci nazwa konkretnego atrybutu.

Aby zrobić to, co chcesz, spróbuj coś wzdłuż tych linii:

<?xml version="1.0"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/"> 
     <FlatData> 
      <Details1_Collection> 
       <xsl:apply-templates select="FlatData/Details1_Collection/Details1"/> 
      </Details1_Collection> 
     </FlatData> 
    </xsl:template> 
    <xsl:template match="Details1"> 
     <Details1> 
      <xsl:apply-templates select="@*"/> 
     </Details1> 
    </xsl:template> 
    <xsl:template match="@*"> 
     <xsl:element name="{name()}"> 
      <xsl:value-of select="."/> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 
2

Czy ta transformacja daje wynik chcesz?

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 

    <xsl:output method="xml" indent="yes" encoding="utf-8" /> 

    <xsl:template match="//Details1"> 
     <Details1> 
      <xsl:for-each select="@*"> 
       <xsl:element name="{name(.)}"><xsl:value-of select="." /></xsl:element> 
      </xsl:for-each> 
     </Details1> 
    </xsl:template> 

</xsl:stylesheet> 
+0

Wynika to w pliku XML z niemal tyle linii, ile oryginalny, wejściowy kod XML, ale ze wszystkimi z nich pusty zapisuje pierwszy wiersz zawierający '>. –

+0

Okazuje się, że mam puste linie zamiast danych, które chciałem z powodu problemu z przestrzenią nazw; zaktualizowane pytanie, dodałem własną odpowiedź. –

0

inny sposób napisać odpowiedź Jörn Horstmann (jeśli trzeba to zrobić z Details1, Details2, i tak dalej ...) Byłoby:

<xsl:template match="//Details1 | //Details2 | //whatever"> 
    <xsl:copy> 
    <xsl:apply-templates select="@*"/> 
    </xsl:copy> 
</xsl:template> 

<xsl:template match="@*"> 
    <xsl:element name="{name(.)}"> 
    <xsl:value-of select="." /> 
    </xsl:element> 
</xsl:template> 
0

Prawdopodobnie najprostszym sposobem, aby to zrobić:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output indent="yes"/> 

    <xsl:template match="/"> 
    <FlatData> 
     <xsl:copy-of select="//Details1" /> 
    </FlatData> 
    </xsl:template> 
</xsl:stylesheet> 
+1

Niezupełnie - to po prostu kopiuje elementy takie jakie są, a pytanie dotyczy tłumaczenia atrybutów na elementy. –

3

Aby rozwiązać problem przestrzeni nazw (dla obu wskazań), dodać deklarację przestrzeni nazw z przedrostkiem do swojej XLST:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
       xmlns:r="MyReport" 
       version="1.0"> 

a następnie używać go we wszystkich wyrażeń XPath, aby zakwalifikować się elementy, na przykład:

<xsl:template match="//r:Details1">