2010-12-16 3 views
2

Wir haben ein XML-Format, das eigentlich nur HTML mit einigen zusätzlichen Gubbins ist. Es definiert, welche HTML-Elemente editierbar sind und welche Attribute editiert werden können.Konvertieren von XML-Tags in Attribute an beliebigen Orten mit XSLT

Hier ist ein Beispiel

<img src="images/placeholder.jpg" 
    alt="Placeholder" 
    width="600" 
    height="250" 
    border="0"> 
    <var attr="src" /> 
    <var attr="height" ok="150-300" /> 
</img> 

Die XML ist so die Vorlagen sind leichter zu schreiben, aber ich muss es gültig (ish) HTML konvertieren. Um dies zu tun ich es in zusammenzubrechen will:

<img src="images/placeholder.jpg" 
    alt="Placeholder" 
    width="600" 
    height="250" 
    border="0" 
    editable="src height" 
    constraints="height:150-300"> 

Ich kann dies tun für <img>, aber das Problem ist, dass die <var> Tags tatsächlich als Kind jeden Elements in der Seite angezeigt werden können. In allen Fällen ist der Algorithmus zum Konvertieren in Attribute derselbe, aber was ich nicht herausfinden kann, ist eine XSLT-Vorlage anzugeben, die mit dem Elternelement eines Tags <var> übereinstimmen kann. Ich versuchte match="var/..", aber das erwies sich als ungültig.

Die Alternative wäre, die <var> s und fügen sie als Attribute zu ihren Eltern hinzu, aber ich glaube, dass an diesem Punkt in der Verarbeitung dieses bestimmte Schiff bereits gesegelt hätte.

Ist das machbar?

Thankies

Antwort!

I kombiniert die vollständigere Antwort mit nutzbringend genaue Antwort des Dimitre folgendes zu bilden:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="*[var]"> 
     <xsl:copy > 
      <xsl:attribute name="editable"> 
       <xsl:for-each select="var[@attr]"> 
        <xsl:value-of 
         select="concat(@attr, 
          substring(' ', 
           1 div (position()!=last())))"/> 
       </xsl:for-each> 
      </xsl:attribute> 
      <xsl:attribute name="constraints"> 
       <xsl:for-each select="var[@ok]"> 
        <xsl:value-of 
         select="concat(@attr,':',@ok, 
          substring(';', 
           1 div (position()!=last())))"/> 
       </xsl:for-each> 
      </xsl:attribute> 
      <xsl:apply-templates select="@*"/> 
     </xsl:copy> 
    </xsl:template> 

    <xsl:template match="var"> 
    </xsl:template> 

    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|node()"/> 
     </xsl:copy> 
    </xsl:template> 
</xsl:stylesheet> 

Leider arbeiten gerade die genaue Antwort Alejandro gab nicht weg (noch nicht sicher, warum), aber diese Kombination seiner Antwort und Antwort Dmitri scheint der Job gut

getan zu haben :)
+0

Gute Frage, +1. Siehe meine Antwort für die natürlichste XSLT-Lösung. :) –

Antwort

1

Neben Dimitres genaue Antwort auf Ihre Frage wäre ein anderer Ansatz:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:template match="@*|node()"> 
     <xsl:copy> 
      <xsl:apply-templates select="@*|var"/> 
      <xsl:apply-templates select="node()[not(self::var)]"/> 
     </xsl:copy> 
    </xsl:template> 
    <xsl:template match="var"/> 
    <xsl:template match="var[1]"> 
     <xsl:attribute name="editable"> 
      <xsl:for-each select="../var/@attr"> 
       <xsl:value-of 
        select="concat(., 
            substring(' ', 
               1 div (position()!=last())))"/> 
      </xsl:for-each> 
     </xsl:attribute> 
     <xsl:attribute name="constraints"> 
      <xsl:for-each select="../var/@ok"> 
       <xsl:value-of 
        select="concat(../@attr,':',., 
            substring(';', 
               1 div (position()!=last())))"/> 
      </xsl:for-each> 
     </xsl:attribute> 
    </xsl:template> 
</xsl:stylesheet> 

Ausgang:

<img src="images/placeholder.jpg" 
    alt="Placeholder" 
    width="600" 
    height="250" 
    border="0" 
    editable="src height" 
    constraints="height:150-300"></img> 
+0

Kudos für die epische Voraussicht, um all die anderen Dinge zu veranschaulichen, für die ich viel Zeit haben würde, wie das concat-Zeug :) Ich akzeptierte diese Antwort für ihre Vollständigkeit – Altreus

+0

hmm Ich werde hacken müssen Dies seit meinem einfachen Beispiel funktioniert nicht. Aber ich denke, ich bin auf dem richtigen Weg :) – Altreus

+0

@Altreus: Das Problem könnte sein, weil 'var' Elemente nicht das erste Kind sind, einschließlich Leerzeichen nur Textknoten, die sie in (X) HTML gemein sind. Einfache Lösung beinhaltet eine geringfügige Änderung der Identitätsregel. Überprüfen Sie meine Bearbeitung. –

1

ich würde eine lokale Variable Gebäude (<xsl:variable>) als der Parser zum <img> Tag bekommt und einen neuen <img ...> explizit innerhalb dieser variablen zu konstruieren, zu Fuß durch alle <var> Kinder es findet (<xsl:foreach ...> jemand?) Schließen Sie die Variable, wenn sie erschöpft sind ... dann schreiben Sie einfach die Variable aus?

4

, was ich nicht herausfinden kann, wie zu tun ist eine XSLT-Vorlage angeben, die das übergeordnete Element eines <var> Tag

Verwendung bieten kann:

<xsl:template match="*[var]"> 
+0

+1, yep. @ Altreus, das bedeutet "Übereinstimmung mit einem beliebigen Element, das ein untergeordnetes Element mit dem Namen 'var' hat". – LarsH

+0

Manchmal wünschte ich, ich könnte zwei als die akzeptierte Antwort markieren. Während diese Antwort genau das ist, was ich gefragt habe und mir etwas zeigt, was ich nicht wusste, akzeptierte ich die vollständigere Antwort, weil ich die immense Voraussicht hatte, alle anderen Fragen zu diesem Beispiel zu beantworten, das ich unausweichlich bekommen würde: D – Altreus

Verwandte Themen