2009-03-15 9 views
2

Ich habe einen Satz von Dokumenten, die implizit die zulässigen Felder für einen zweiten Satz von Objekten definieren, die in einen dritten Satz von Dokumenten transformiert werden müssen ( ) Welche "Regeln" das zu verwendende Dokument verwenden, hängt von dem Inhalt der Datei ab, die transformiert wird, zMit xslt ein XML-Dokument basierend auf dem Inhalt eines zweiten XML-Dokuments transformieren

<!-- One example rules document --> 
<document object="obj1_rules"> 
<field name="A"/> 
<field name="B"/> 
<field name="C"/> 
</document> 

<!-- Document to be tranformed based upon obj1_rules--> 
<document object="obj1"> 
<field name="A"/> 
<field name="B"/> 
<field name="C"/> 
<field name="D"/> 
<field name="E"/> 
</document> 

<!-- Desired result--> 
<document object="obj1"> 
<newfield name="A"/> 
<newfield name="B"/> 
<newfield name="C"/> 
</document> 

Ist es möglich, diese Transformation mit xslt zu tun?

Ich sehe, dass "There is no way in XSLT of constructing XPath expressions (e.g. variable references) at run-time." So bin ich kein Glück, oder ich sehe gerade dieses Problem falsch? Vielen Dank!

+0

Überprüfen Sie dies http://stackoverflow.com/questions/336572/filter-xml-based-on-another-xml-using-xslt-1 –

Antwort

2

ist eine einfache Lösung:

Diese Transformation:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
    <xsl:output omit-xml-declaration="yes" indent="yes"/> 
    <xsl:strip-space elements="*"/> 
<!--             --> 
    <xsl:variable name="vrtfRules"> 
     <document object="obj1_rules"> 
      <field name="A"/> 
      <field name="B"/> 
      <field name="C"/> 
     </document> 
    </xsl:variable> 
<!--             --> 
    <xsl:variable name="vRules" select= 
    "document('')/*/xsl:variable 
        [@name = 'vrtfRules'] 
        /* 
    "/> 
<!--             --> 
    <xsl:template match="node()|@*"> 
     <xsl:copy> 
      <xsl:apply-templates select="node()|@*"/> 
     </xsl:copy> 
    </xsl:template> 
<!--             --> 
    <xsl:template match="field"> 
     <xsl:if test="@name = $vRules/*/@name"> 
     <newfield> 
      <xsl:apply-templates select="node()|@*"/> 
     </newfield> 
     </xsl:if> 
    </xsl:template> 
</xsl:stylesheet> 

wenn auf dem originaly bereitgestellten XML-Quelldokument angewandt:

<document object="obj1"> 
    <field name="A"/> 
    <field name="B"/> 
    <field name="C"/> 
    <field name="D"/> 
    <field name="E"/> 
</document> 

pr oduces das gewünschte Ergebnis:

<document object="obj1"> 
    <newfield name="A"/> 
    <newfield name="B"/> 
    <newfield name="C"/> 
</document> 

Hinweis, dass die „Regeln Dokument“ im Sheet nur für Kompaktheit ist. Wenn es sich um ein separates Dokument handelt, muss nur die verwendete document() Funktion mit dem tatsächlichen href angepasst werden.

1

Vielleicht bin ich zu einfach, aber gibt es einen Grund, warum Ihr "Regeldokument" nicht einfach ein XSLT sein kann?

+0

+1. Das wäre meine bevorzugte Vorgehensweise. –

+0

Leider, weil dies die Anforderungen sind, die ich bekam. :-) – Atlas1j

1

Nun, ich kann sehen, warum Sie Regeln lieber in einer einfachen XML-Datei als in einem vollwertigen xsl-Stylesheet haben möchten, aber Sie überspringen einfach einen Schritt.

Sie müssen ein xsl-Stylesheet erstellen, das Ihr XML-Regeldokument in ein xsl-Stylesheet umwandelt, das Sie dann auf Ihre Quell-XML anwenden.

Der Trick ist mit Namespaces und nicht durch die Mischung von xsl Regeln angewendet und xsl Regeln generiert verwirrt.

 
    <?xml version="1.0" ?> 
    <xsl:stylesheet 
     xmlns="YOUR_NAMESPACE_HERE" 
     xmlns:output="http://www.w3.org/1999/XSL/Transform" 
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
     version="2.0"> 

     <xsl:output 
      method="xml" 
      indent="yes" 
      media-type="text/xsl" /> 

     <xsl:template match="/"> 
      <output:stylesheet version="2.0"> 
       <xsl:apply-templates /> 
      </output:stylesheet> 
     </xsl:template> 

     <xsl:template match="document[@object]"> 
      <output:template match="document[@object='{@object}']"> 
       <output:copy> 
        <xsl:apply-templates /> 
       </output:copy> 
      </output:template> 
     </xsl:template> 

     <xsl:template match="field[@name]"> 
      <output:if test="field[@name='{@name}']"> 
       <output:copy-of select="field[@name='{@name}']" /> 
      </output:if> 
     </xsl:template> 

    </xsl:stylesheet> 

Ich vermute Sie das gleiche Dokument-Objekt-Attribut in den Regeln verwenden würden und in den Dokumenten selbst (das ist viel einfacher imo).

So, Sie führen Ihre Regeln Dokument über das Stylesheet oben. Das Ergebnis ist ein neues XSL-Stylesheet, das genau das tut, was Sie in Ihrem XML-Regeldokument beschreiben. Sie wenden dann dieses resultierende Stylesheet auf Ihr Quelldokument an und Sie sollten das erwartete Ergebnis erhalten. Hier