DeRPiNkY: XSLT zusammen mit XML-Schema ?

Hi,

ich habe eine grundsätzliche Frage:
Ich hab eine Reihe von XML-Dokumenten erstellt, die durch XML-Schema validiert werden, nun möchte ich diese mittels XSLT in HTML umwandeln, um eine geeignete Browserdarstellung zu generieren. Jedoch klappt das nicht so wie ich das gerne hätte, genaugenommen überhaupt nicht!
Im Dokument-Element der XML-Dokumente muss ja das entsprechende Schema eingebunden sein.

<Article xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.bernd.de Article-Schema.xsd"
  xmlns="http://www.bernd.de">

Nun stellt sich die Frage wie dann das Template im XSLT-Dokument aufgebaut werden muss, welches für dieses Dokument-Element des HTML-Code erzeugt?

Etwa:
<xsl:template match="/">
Oder:
<xsl:template match="Article">
<!--Dokumentelement heisst "Article" -->

Oder wie sonst??
Das klappt alles nicht!

Vielen Dank für eure Hilfe!

CU Bernd

  1. Hallo,

    ich habe eine grundsätzliche Frage:
    Ich hab eine Reihe von XML-Dokumenten erstellt, die durch XML-Schema validiert werden, nun möchte ich diese mittels XSLT in HTML umwandeln, um eine geeignete Browserdarstellung zu generieren. Jedoch klappt das nicht so wie ich das gerne hätte, genaugenommen überhaupt nicht!
    Im Dokument-Element der XML-Dokumente muss ja das entsprechende Schema eingebunden sein.

    <Article xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.bernd.de Article-Schema.xsd"
      xmlns="http://www.bernd.de">

    Du musst auch im xsl:stylesheet den Namensraum für deine Elemente angeben.

    Grüße
    Thomas

    --
    Surftip: kennen Sie schon Pipolino's Clowntheater?
    http://www.clowntheater-pipolino.net/
    1. Hallo,

      ich habe eine grundsätzliche Frage:
      Ich hab eine Reihe von XML-Dokumenten erstellt, die durch XML-Schema validiert werden, nun möchte ich diese mittels XSLT in HTML umwandeln, um eine geeignete Browserdarstellung zu generieren. Jedoch klappt das nicht so wie ich das gerne hätte, genaugenommen überhaupt nicht!
      Im Dokument-Element der XML-Dokumente muss ja das entsprechende Schema eingebunden sein.

      <Article xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.bernd.de Article-Schema.xsd"
        xmlns="http://www.bernd.de">

      Du musst auch im xsl:stylesheet den Namensraum für deine Elemente angeben.

      Grüße
      Thomas

      Hi Thomas,
      vielen Dank für deine Antwort, aber was genau meinst du denn?
      Könntest du ein kleines Beispiel beschreiben oder so?

      Meinst du beim template?
      So hab ichs schon mal versucht, ging aber nicht!

      <xsl:template match="Article @xsi:schemaLocation='http://www.bernd.de Article.xsd'
      @xmlns='http://www.bernd.de'
      @xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'">

      Oder meinst du irgendwas anderes?

      Vielen Dank schon mal im Voraus!

      CU Bernd

      1. Hallo,

        Hi Thomas,
        vielen Dank für deine Antwort, aber was genau meinst du denn?
        Könntest du ein kleines Beispiel beschreiben oder so?

        Meinst du beim template?
        So hab ichs schon mal versucht, ging aber nicht!

        <xsl:template match="Article @xsi:schemaLocation='http://www.bernd.de Article.xsd'
        @xmlns='http://www.bernd.de'
        @xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'">

        So kann es nicht gehen.

        Oder meinst du irgendwas anderes?

        Ja ich meinte was anderes.
        Dein bzw. das Problem ist der 'default' Namesraum in deinem XML (xmlns="http://www.bernd.de") genauer: XSLT 1 hat damit Probleme.

        Du hast zwei Möglichkeiten, entweder du gibst jedem deiner Elemente ein Prefix:
        <B:Article xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bernd.de/Article-Schema.xsd" xmlns:B="http://www.bernd.de">
            <B:data>bla</B:data>
         </B:Article>

        dann geht es so:
        <?xml version="1.0" encoding="UTF-8"?>
        <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:B="http://www.bernd.de" exclude-result-prefixes="B">
            <xsl:template match="/">
                <html>
                    <head>
                        <title>Untitled</title>
                    </head>
                    <body>
                        <xsl:apply-templates />
                    </body>
                </html>
            </xsl:template>
            <xsl:template match="B:Article">
                <div>
                    <xsl:apply-templates />
                </div>
            </xsl:template>
            <xsl:template match="B:data">
                <h1><xsl:value-of select="."/></h1>
            </xsl:template>
        </xsl:stylesheet>

        oder du musst in deinem XSL "herumgurken", und zwar so:

        <?xml version="1.0" encoding="UTF-8"?>
        <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
            <xsl:template match="/">
                <html>
                    <head>
                        <title>Untitled</title>
                    </head>
                    <body>
                        <xsl:apply-templates />
                    </body>
                </html>
            </xsl:template>
            <xsl:template match="*[name() = 'Article']">
                <div>
                    <xsl:apply-templates />
                </div>
            </xsl:template>
            <xsl:template match="*[name() = 'data']">
                <h1><xsl:value-of select="."/></h1>
            </xsl:template>
        </xsl:stylesheet>

        Erst XSLT 2 wird dieses Problem beheben.

        Grüße
        Thomas

        --
        Surftip: kennen Sie schon Pipolino's Clowntheater?
        http://www.clowntheater-pipolino.net/
        1. Hallo,

          Hi Thomas,
          vielen Dank für deine Antwort, aber was genau meinst du denn?
          Könntest du ein kleines Beispiel beschreiben oder so?

          Meinst du beim template?
          So hab ichs schon mal versucht, ging aber nicht!

          <xsl:template match="Article @xsi:schemaLocation='http://www.bernd.de Article.xsd'
          @xmlns='http://www.bernd.de'
          @xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'">

          So kann es nicht gehen.

          Oder meinst du irgendwas anderes?

          Ja ich meinte was anderes.
          Dein bzw. das Problem ist der 'default' Namesraum in deinem XML (xmlns="http://www.bernd.de") genauer: XSLT 1 hat damit Probleme.

          Du hast zwei Möglichkeiten, entweder du gibst jedem deiner Elemente ein Prefix:
          <B:Article xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.bernd.de/Article-Schema.xsd" xmlns:B="http://www.bernd.de">
              <B:data>bla</B:data>
          </B:Article>

          dann geht es so:
          <?xml version="1.0" encoding="UTF-8"?>
          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:B="http://www.bernd.de" exclude-result-prefixes="B">
              <xsl:template match="/">
                  <html>
                      <head>
                          <title>Untitled</title>
                      </head>
                      <body>
                          <xsl:apply-templates />
                      </body>
                  </html>
              </xsl:template>
              <xsl:template match="B:Article">
                  <div>
                      <xsl:apply-templates />
                  </div>
              </xsl:template>
              <xsl:template match="B:data">
                  <h1><xsl:value-of select="."/></h1>
              </xsl:template>
          </xsl:stylesheet>

          oder du musst in deinem XSL "herumgurken", und zwar so:

          <?xml version="1.0" encoding="UTF-8"?>
          <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
              <xsl:template match="/">
                  <html>
                      <head>
                          <title>Untitled</title>
                      </head>
                      <body>
                          <xsl:apply-templates />
                      </body>
                  </html>
              </xsl:template>
              <xsl:template match="*[name() = 'Article']">
                  <div>
                      <xsl:apply-templates />
                  </div>
              </xsl:template>
              <xsl:template match="*[name() = 'data']">
                  <h1><xsl:value-of select="."/></h1>
              </xsl:template>
          </xsl:stylesheet>

          Erst XSLT 2 wird dieses Problem beheben.

          Grüße
          Thomas

          Hi Thomas,

          vielen Dank für die sehr hilfreiche Antwort!
          Die Möglichkeit mit dem Prefix im XML-Dokument fällt leider weg, bleibt also nur noch die Änderung des XSLT-Codes. Hast du vielleicht noch ne Idee wie man das mit dem <xsl:apply-templates /> hinbekommen könnte? Ich brauch das in dieser Reihenfolge:

          <body>
          <xsl:apply-templates select="*[name()='Head']"/>
          <xsl:apply-templates select="*[name()='BOM']"/>
          <xsl:apply-templates select="*[name()='Head']" mode="toc"/>
          </body>

          wie wähle ich aber diese Templates aus? So geht das nicht.

          Ich muss doch dann bei jedem einzelnen Element mit
          <h1><xsl:value-of select="*[name()='ELEMENT']"/></h1>
          den entsprechenden Wert rausholen oder???

          Irgendwie ziemlich scheisse dass des nicht gscheit unterstützt wird!

          Nochmals vielen vielen Dank, ohne dich wäre ich da nie draufgekommen, besonders weils dazu im Netz nichts zu geben scheint!

          Schönen Tag noch!

          Cu Bernd

          1. Hallo,

            vielen Dank für die sehr hilfreiche Antwort!
            Die Möglichkeit mit dem Prefix im XML-Dokument fällt leider weg, bleibt also nur noch die Änderung des XSLT-Codes. Hast du vielleicht noch ne Idee wie man das mit dem <xsl:apply-templates /> hinbekommen könnte? Ich brauch das in dieser Reihenfolge:

            <body>
            <xsl:apply-templates select="*[name()='Head']"/>
            <xsl:apply-templates select="*[name()='BOM']"/>
            <xsl:apply-templates select="*[name()='Head']" mode="toc"/>
            </body>

            wie wähle ich aber diese Templates aus? So geht das nicht.

            Du muss den Pfad anpassen, wie würdest du es "normal" machen?
            Basierend auf mein vorheriges XSL:
            <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
                <xsl:template match="/">
                    <html>
                        <head>
                            <title>Untitled</title>
                        </head>
                        <body>
                            <xsl:apply-templates select="./*[name() = 'Article']" />
                        </body>
                    </html>
                </xsl:template>
                <xsl:template match="*[name() = 'Article']">
                    <div>
                        <xsl:apply-templates select="./*[name() = 'data']" />
                    </div>
                </xsl:template>
                <xsl:template match="*[name() = 'data']">
                    <h1><xsl:value-of select="."/></h1>
                </xsl:template>
            </xsl:stylesheet>

            Wenn der Pfad bei dir anderes ist, muss du das leider entsprechend angeben
            <xsl:apply-templates select="*[name() = 'Article']/*[name() = 'ELEMENT]" />

            <xsl:apply-templates select="*[name() = 'Article']/*[name() = 'ELEMENT][@attribut = 'WERT']" />  etc.

            Ich muss doch dann bei jedem einzelnen Element mit
            <h1><xsl:value-of select="*[name()='ELEMENT']"/></h1>
            den entsprechenden Wert rausholen oder???

            Ja.

            Irgendwie ziemlich scheisse dass des nicht gscheit unterstützt wird!

            Leider, und XSLT 2 ist noch nicht wirklich zum produktiven Einsatzt geeignet.

            Grüße
            Thomas

            PS: eigentlich müsstest du statt name() local-name() verwenden, aber in deinem Fall ist es gleich.

            --
            Surftip: kennen Sie schon Pipolino's Clowntheater?
            http://www.clowntheater-pipolino.net/
            1. Hallo,

              vielen Dank für die sehr hilfreiche Antwort!
              Die Möglichkeit mit dem Prefix im XML-Dokument fällt leider weg, bleibt also nur noch die Änderung des XSLT-Codes. Hast du vielleicht noch ne Idee wie man das mit dem <xsl:apply-templates /> hinbekommen könnte? Ich brauch das in dieser Reihenfolge:

              <body>
              <xsl:apply-templates select="*[name()='Head']"/>
              <xsl:apply-templates select="*[name()='BOM']"/>
              <xsl:apply-templates select="*[name()='Head']" mode="toc"/>
              </body>

              wie wähle ich aber diese Templates aus? So geht das nicht.

              Du muss den Pfad anpassen, wie würdest du es "normal" machen?
              Basierend auf mein vorheriges XSL:
              <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
                  <xsl:template match="/">
                      <html>
                          <head>
                              <title>Untitled</title>
                          </head>
                          <body>
                              <xsl:apply-templates select="./*[name() = 'Article']" />
                          </body>
                      </html>
                  </xsl:template>
                  <xsl:template match="*[name() = 'Article']">
                      <div>
                          <xsl:apply-templates select="./*[name() = 'data']" />
                      </div>
                  </xsl:template>
                  <xsl:template match="*[name() = 'data']">
                      <h1><xsl:value-of select="."/></h1>
                  </xsl:template>
              </xsl:stylesheet>

              Wenn der Pfad bei dir anderes ist, muss du das leider entsprechend angeben
              <xsl:apply-templates select="*[name() = 'Article']/*[name() = 'ELEMENT]" />

              <xsl:apply-templates select="*[name() = 'Article']/*[name() = 'ELEMENT][@attribut = 'WERT']" />  etc.

              Ich muss doch dann bei jedem einzelnen Element mit
              <h1><xsl:value-of select="*[name()='ELEMENT']"/></h1>
              den entsprechenden Wert rausholen oder???

              Ja.

              Irgendwie ziemlich scheisse dass des nicht gscheit unterstützt wird!

              Leider, und XSLT 2 ist noch nicht wirklich zum produktiven Einsatzt geeignet.

              Grüße
              Thomas

              PS: eigentlich müsstest du statt name() local-name() verwenden, aber in deinem Fall ist es gleich.

              Klingt plausibel, ich brings aber irgendwie immer noch nicht zum laufen, bin einfach zu blöd scheinbar!

              Hier mein Code:

              <xsl:template match="/">
              <html>
              <head>
              <title>Stueckliste</title>
              </head>
              <body>
              <xsl:apply-templates select="./*[name()='Head']"/>
              <xsl:apply-templates select="./*[name()='BOM']"/>
              <xsl:apply-templates select="./*[name()='Head']" mode="toc"/>
              </body>
              </html>
              </xsl:template>

              <!-- Darstellung der Kopfdaten  - - - -  -->

              <xsl:template match="*[name()='Article']/*[name()='Head']">
              <table class="tab1" bgcolor="#c0c0c0" bordercolor="black" width="650px" heigth="40px" cellspacing="0" cellpadding="0">
              <colgroup>
              <col width="60px"></col>
              <col width="85px"></col>
              <col width="155px"></col>
              <col width="30px"></col>
              <col width="45px"></col>
              <col width="75px"></col>
              <col width="200px"></col>
              </colgroup>
              <tr>
              <td class="border1" rowspan="2" height="10px"><p align="center">Siemens PTD&#160;T</p></td>
              <td class="border1" rowspan="2"><p align="center">engeneering <font size="3">BOM</font></p></td>
              <td class="border1" bgcolor="#007575"><font color="white"><p>&#160;ident no. -EX</p></font></td>
              <td class="border1" bgcolor="#007575"><font color="white"><p>&#160;RI</p></font></td>
              usw....

              Das XML-Dokument schaut folgendermaßen aus:

              <Article xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
                       xsi:schemaLocation='http://www.bernd.de Article-Schema.xsd'
                xmlns='http://www.bernd.de'>
               <Head>
                <ART.PartID></ART.PartID>
                <ART.ZNr></ART.ZNr>
                <ART.WeightC></ART.WeightC>
                .
                              .
                              .
                <ART.Surface></ART.Surface>
                <ART.MatText></ART.MatText>
               </Head>
               <BOM>
                <Position>
                 <ARTART.PosNo></ARTART.PosNo>
                 <ARTART.PartID></ARTART.PartID>
                 .
                                      .
                                      .

              kannst du was damit anfangen?
              Vielen Dank!

              Cu Bernd

              1. Klingt plausibel, ich brings aber irgendwie immer noch nicht zum laufen, bin einfach zu blöd scheinbar!

                Hier mein Code:

                <xsl:template match="/">
                <html>
                <head>
                <title>Stueckliste</title>
                </head>
                <body>
                <xsl:apply-templates select="./*[name()='Head']"/>
                <xsl:apply-templates select="./*[name()='BOM']"/>
                <xsl:apply-templates select="./*[name()='Head']" mode="toc"/>
                </body>
                </html>
                </xsl:template>

                <!-- Darstellung der Kopfdaten  - - - -  -->

                <xsl:template match="*[name()='Article']/*[name()='Head']">
                <table class="tab1" bgcolor="#c0c0c0" bordercolor="black" width="650px" heigth="40px" cellspacing="0" cellpadding="0">
                <colgroup>
                <col width="60px"></col>
                <col width="85px"></col>
                <col width="155px"></col>
                <col width="30px"></col>
                <col width="45px"></col>
                <col width="75px"></col>
                <col width="200px"></col>
                </colgroup>
                <tr>
                <td class="border1" rowspan="2" height="10px"><p align="center">Siemens PTD&#160;T</p></td>
                <td class="border1" rowspan="2"><p align="center">engeneering <font size="3">BOM</font></p></td>
                <td class="border1" bgcolor="#007575"><font color="white"><p>&#160;ident no. -EX</p></font></td>
                <td class="border1" bgcolor="#007575"><font color="white"><p>&#160;RI</p></font></td>
                usw....

                Das XML-Dokument schaut folgendermaßen aus:

                <Article xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
                         xsi:schemaLocation='http://www.bernd.de Article-Schema.xsd'
                  xmlns='http://www.bernd.de'>
                <Head>
                  <ART.PartID></ART.PartID>
                  <ART.ZNr></ART.ZNr>
                  <ART.WeightC></ART.WeightC>
                  .
                                .
                                .
                  <ART.Surface></ART.Surface>
                  <ART.MatText></ART.MatText>
                </Head>
                <BOM>
                  <Position>
                   <ARTART.PosNo></ARTART.PosNo>
                   <ARTART.PartID></ARTART.PartID>
                   .
                                        .
                                        .

                kannst du was damit anfangen?
                Vielen Dank!

                Cu Bernd

                AH,

                hat doch so ungefähr gestimmt wie du das gesagt hast!
                Bist und bleibst einfach der Chef!
                Jetzt gehts:

                <xsl:template match="//*[name() = 'Article']">
                <html>
                <head>
                <title>Stueckliste</title>
                </head>
                <body>
                <xsl:apply-templates select="*[name() ='Head']"/>
                <xsl:apply-templates select="*[name()='BOM']"/>
                <xsl:apply-templates select="*[name()='Head']" mode="toc"/>
                </body>
                </html>
                </xsl:template>

                und

                <xsl:template match="//*[name() = 'Head']">

                <table class="tab1" bgcolor="#c0c0c0" bordercolor="black" width="650px" heigth="40px" cellspacing="0" cellpadding="0">
                <colgroup>
                <col width="60px"></col>
                <col width="85px"></col>
                <col width="155px"></col>
                <col width="30px"></col>
                <col width="45px"></col>
                <col width="75px"></col>
                <col width="200px"></col>
                </colgroup>
                <tr>
                <td class="border1" rowspan="2" height="10px"><p align="center">Siemens PTD&#160;T</p></td>
                <td class="border1" rowspan="2"><p align="center">engeneering <font size="3">BOM</font></p></td>
                <td class="border1" bgcolor="#007575"><font color="white"><p>&#160;ident no. -EX</p></font></td>
                <td class="border1" bgcolor="#007575"><font color="white"><p>&#160;RI</p></font></td>
                usw....

                Vielen Vielen Dank für deine Hilfe!

                noch eine Frage: was ist der unterschied zwischen name() und local-name() ?
                Schönen Tag noch!

                Cu Bernd

                1. Hallo,

                  Gleich eine Bitte: bitte keine Vollzitate in Postings, wenn es nicht _unbedingt_ notwendig ist, macht das Lesen sehr schwer.

                  <xsl:template match="/*[name() = 'Article']">
                  <html>
                  <head>
                  <title>Stueckliste</title>
                  </head>
                  <body>
                  <xsl:apply-templates select="*[name()='Head']"/>
                  <xsl:apply-templates select="*[name()='BOM']"/>
                  <xsl:apply-templates select="*[name()='Head']" mode="toc"/>
                  </body>
                  </html>
                  </xsl:template>

                  Dann reicht ein:
                  <xsl:template match="*[name() = 'Head']">
                  statt:
                  <xsl:template match="//*[name() = 'Head']">

                  noch eine Frage: was ist der unterschied zwischen name() und local-name() ?

                  Für Element = <abc:foo xmlns:abc="http://example.com/abc">
                  name() = 'abc:foo'
                  local-name() = 'foo'
                  namespace-uri() = 'http://example.com/abc'

                  Grüße
                  Thomas

                  --
                  Surftip: kennen Sie schon Pipolino's Clowntheater?
                  http://www.clowntheater-pipolino.net/
                  1. Gleich eine Bitte: bitte keine Vollzitate in Postings, wenn es nicht _unbedingt_ notwendig ist, macht das Lesen sehr schwer.

                    Ok, ich versuche mich dran zu halten.

                    Dann reicht ein:
                    <xsl:template match="*[name() = 'Head']">
                    statt:
                    <xsl:template match="//*[name() = 'Head']">

                    Noch besser, dankeschön!

                    noch eine Frage: was ist der unterschied zwischen name() und local-name() ?

                    Für Element = <abc:foo xmlns:abc="http://example.com/abc">
                    name() = 'abc:foo'
                    local-name() = 'foo'
                    namespace-uri() = 'http://example.com/abc'

                    Ok, spielt also für meine Verwendung wirklich keine Rolle!

                    So, jetzt müsste ich das alles so halbwegs verstanden haben!
                    Vielen Dank nochmal, ist echt beeindruckend dass es Leute gibt die freiwillig und unentgeldlich helfen! RESPEKT!

                    Schönen Tag noch!

                    CU Bernd