Mit XSLT-Transformation ein XML-Dokuments basierend auf den Inhalt eines zweiten XML-Dokuments

StackOverflow https://stackoverflow.com/questions/647324

  •  22-07-2019
  •  | 
  •  

Frage

Ich habe eine Reihe von Dokumenten, die implizit die erlaubten Felder für einen zweiten Satz von Objekten definieren, die in einen dritten Satz von Dokumenten umgewandelt werden müssen ( die „Regeln“ Dokument zu verwenden, hängt von dem Inhalt der Datei umgewandelt wird), z.B.

<!-- 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 "Es gibt keine Möglichkeit, in XSLT von XPath-Ausdrücken konstruieren ( zB Variablenreferenzen) zur Laufzeit. " Also habe ich kein Glück bin, oder ich bin auf der Suche nur auf dieses Problem falsch? Dank!

War es hilfreich?

Lösung

Hier 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>

erzeugt das gewünschte Ergebnis:

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

Hinweis , dass das „Regeln Dokument“ im Sheet ist nur für Kompaktheit. Wann ist es ein separates Dokument, nur die document() Funktion eingestellt mit dem tatsächlichen href werden müssen, verwendet.

Andere Tipps

Vielleicht bin ich zu stark zu vereinfachen, aber gibt es einen Grund, warum Ihr „Regeln Dokument“ kann nicht einfach ein XSLT sein?

Nun, ich kann sehen, warum Sie Regeln in einer einfachen XML-Datei haben mögen, statt in einem vollwertigen XSL-Stylesheet aber du bist einfach einen Schritt zu überspringen.

Sie müssen einen XSL-Stylesheet, dass Ihr XML-Regel-Dokument in einen XSL-Stylesheet verwandeln, die Sie dann auf Ihre Quelle xml anwenden.

Der Trick mit Namespaces und nicht durch die Mischung aus xsl Regeln verwirrte angewandt und xsl Regeln erzeugt werden.

    <?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 führen Sie Ihre Regeln Dokument über das Sheet oben. Das Ergebnis ist ein neuer XSL-Stylesheet, das genau das tut, was Sie in Ihrem XML-Regel-Dokument beschreiben. Sie gelten dann diese resultierende Sheet auf Ihrem Quelldokument und Sie sollten das Ergebnis Sie erwarten, erhalten.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top