Announcement

Collapse
No announcement yet.

XSLT Debugger: Unknown namespace prefix

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • XSLT Debugger: Unknown namespace prefix

    Hi,

    ich transformiere mein Quell-XML in mein Ziel-XML mit

    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        
        <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
        
        <xsl:variable name="Prefix" select="'tblAbc_'"/>
        
        <xsl:template match="/">
            <xsl:apply-templates select="dataroot/tblAbc_TadigAbc" mode="root"/>
        </xsl:template>
        
        <!-- Root element -->
        <xsl:template match="*" mode="root">
            <the-abc:THEABC 
                xmlns:the-abc="https://www.xyz.org/THE-ABC" 
                xmlns:the-gen="https://www.xyz.org/THE-GEN" 
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                xsi:schemaLocation="https://www.xyz.org/THE-GEN the-gen-1.2.xsd https://www.xyz.org/THE-ABC the-abc-3.4.xsd">
            <xsl:for-each select="child::node()">
                <xsl:choose>
                    <xsl:when test="child::node()/child::node()">
                        <xsl:apply-templates select="." mode="container"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:apply-templates select="." mode="element"/>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:for-each>
            </the-abc:THEABC>
        </xsl:template>
        
        <!-- Container element -->
        <xsl:template match="*" mode="container">
            <xsl:variable name="Container">
                <xsl:apply-templates select="." mode="translateContainer"/>
            </xsl:variable>
            <xsl:element name="{$Container}">
                <xsl:for-each select="child::node()">
                    <xsl:choose>
                        <xsl:when test="child::node()/child::node()">
                            <xsl:choose>
                            <xsl:when test="local-name() = 'tblAbc_SenderAddress'">
                                <xsl:apply-templates select="." mode="address"/>
                            </xsl:when>
                            <xsl:when test="local-name() = 'tblAbc_DeliveryAddress'">
                                <xsl:apply-templates select="." mode="address"/>
                            </xsl:when>
                            <xsl:otherwise>
                                <xsl:apply-templates select="." mode="container"/>
                            </xsl:otherwise>
                            </xsl:choose>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:apply-templates select="." mode="element"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </xsl:for-each>
            </xsl:element>
        </xsl:template>
        
        <!-- Address container -->
        <xsl:template match="*" mode="address">
            <xsl:if test="not(local-name(preceding-sibling::*[1]) = local-name(.))">
                <xsl:variable name="Container">
                    <xsl:apply-templates select="." mode="translateContainer"/>
                </xsl:variable>
                <xsl:element name="{$Container}">
                    <xsl:for-each select="../child::*/child::AddressLine">
                        <xsl:apply-templates select="." mode="element"/>
                    </xsl:for-each>
                </xsl:element>
            </xsl:if>
        </xsl:template>
        
        <!-- Value element -->
        <xsl:template match="*" mode="element">
            <xsl:if test="not(substring-after(local-name(), substring-before(local-name(), 'Id')) = 'Id')">
                <xsl:variable name="Element">
                    <xsl:apply-templates select="." mode="translateElement"/>
                </xsl:variable>
                <xsl:element name="{$Element}">
                    <xsl:value-of select="."/>
                </xsl:element>
            </xsl:if>
        </xsl:template>
        
        <!-- Container translation -->
        <xsl:template match="*" mode="translateContainer">
            <xsl:choose>
            <xsl:when test="local-name() = 'tblAbc_TadigAbc'">
                <xsl:value-of select="'the-abc:THEABC'"/>
            </xsl:when>
            <xsl:when test="local-name() = 'tblAbc_AbcFileHeader'">
                <xsl:value-of select="'the-abc:ABCFileHeader'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="substring-after(local-name(), $Prefix)"/>
            </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
        
        <!-- Value element translation -->
        <xsl:template match="*" mode="translateElement">
            <xsl:choose>
            <xsl:when test="local-name() = 'AbcFilePrefix'">
                <xsl:value-of select="'ABCFilePrefix'"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:value-of select="local-name()"/>
            </xsl:otherwise>
            </xsl:choose>
        </xsl:template>
    
    </xsl:stylesheet>
    Das Root-Template spezifiziert die namespaces. Sobald er aber das Container-Element 'the-abc:ABCFileHeader' erzeugen möchte, bekomme ich die Meldung "XSLT 1.0 Debugger: Unknown namespace prefix".

    Meine Internetrecherche dazu ergab leider keine Hinweise - was könnte hier schieflaufen?
    --
    Cheers Vince

  • #2
    Die Namensräume müssen entsprechend im XSLT-Dokument deklariert werden (analog zu xmlns:xsl="...").

    Comment


    • #3
      Hmmm ...

      Hi,

      Originally posted by Thomas Meinike View Post
      Die Namensräume müssen entsprechend im XSLT-Dokument deklariert werden (analog zu xmlns:xsl="...").
      Das werde ich ausprobieren ... aber warum meckert er dann nicht das Root-Element an, das ja auch bereits das Namespace-Präfix besitzt? Weil es den Namespace gleich "mitliefert"?

      Und was ich darüber hinaus nicht verstehe: Die Elementnamen sind ja im XSLT nirgendwo als Element vorhanden, sondern immer nur als Strings, also 'the-abc:ABCElement' und ich dachte immer, daß nur Elemente validiert werden.
      --
      Cheers Vince

      Comment


      • #4
        Du hast ja zumindest
        Code:
        <xsl:element name="{$Container}">
        da wird ein Elementknoten konstruiert und dabei kann es die Fehlermeldung geben.
        Generell, wenn man Resultatselemente mit Namensräumen in diversen Templates erzeugen will, ist es sinnvoll, die entsprechenden Namensraumdeklarationen direkt beim xsl: stylesheet-Element anzugeben, also
        Code:
        <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                     xmlns:the-abc="https://www.xyz.org/THE-ABC" 
                    xmlns:the-gen="https://www.xyz.org/THE-GEN" 
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        ...
        </xsl:stylesheet>
        dann sind sie in allen Templates bekannt.

        Comment


        • #5
          Ha!

          Hi,

          Originally posted by Martin Honnen View Post
          Du hast ja zumindest
          Code:
          <xsl:element name="{$Container}">
          da wird ein Elementknoten konstruiert und dabei kann es die Fehlermeldung geben.
          Generell, wenn man Resultatselemente mit Namensräumen in diversen Templates erzeugen will, ist es sinnvoll, die entsprechenden Namensraumdeklarationen direkt beim xsl: stylesheet-Element anzugeben, also
          Code:
          <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                       xmlns:the-abc="https://www.xyz.org/THE-ABC" 
                      xmlns:the-gen="https://www.xyz.org/THE-GEN" 
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
          ...
          </xsl:stylesheet>
          dann sind sie in allen Templates bekannt.
          Und wieder dazugelernt - danke!

          Nur noch zwei kleine Ergänzungsfragen:

          Gehe ich recht in der Annahme, daß er mit dem Root-Element kein Problem hatte, da es die Namespace-Declaration gleich "mitgebracht" hat?

          Und noch eine Style Guide Frage: Sollte man bei Namespace-Declarations vom allgemeinen zum speziellen oder umgekehrt (so wie oben) vorgehen? In welcher Reihenfolge wäre es ggf sinnvoller / performanter?

          Aktuell verfahre ich immer nach dem Motto: Erstmal das spezielle / am häufigsten verwandte ... aber vielleicht gibt's ja da eine bessere Regel zu.

          Jetzt läuft's auf jeden Fall ... endlich.
          --
          Cheers Vince

          Comment

          Working...
          X