Announcement

Collapse
No announcement yet.

Workaround: Variable in "template match"

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

  • Workaround: Variable in "template match"

    Hallo,

    ich habe ein XML Dokument, dass ich nahezu 1:1 per XSLT kopieren möchte, jedoch soll ein Regex-Wert mit einem Wert aus einer anderen XML ausgetauscht werden. Folgendes klappt schonmal ganz gut:

    Quell-XML
    HTML Code:
    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <idPkg:Story xmlns:idPkg="http://ns.adobe.com/AdobeInDesign/idml/1.0/packaging" DOMVersion="7.0">
    	<Story Self="ud9" AppliedTOCStyle="n" TrackChanges="false" StoryTitle="$ID/" AppliedNamedGrid="n">
    		<StoryPreference OpticalMarginAlignment="false" OpticalMarginSize="12" FrameType="TextFrameType" StoryOrientation="Horizontal" StoryDirection="LeftToRightDirection"/>
    		<InCopyExportOption IncludeGraphicProxies="true" IncludeAllResources="false"/>
    		<ParagraphStyleRange AppliedParagraphStyle="ParagraphStyle/$ID/NormalParagraphStyle" Justification="CenterAlign">
    			[...]
    			<CharacterStyleRange AppliedCharacterStyle="CharacterStyle/$ID/[No character style]" FillColor="Color/C=0 M=100 Y=0 K=0" FontStyle="Bold" PointSize="18">
    				<Properties>
    					<AppliedFont type="string">Times New Roman</AppliedFont>
    				</Properties>
    				<Content>S </Content>
    			</CharacterStyleRange>
    			<CharacterStyleRange AppliedCharacterStyle="CharacterStyle/$ID/[No character style]" FontStyle="Bold" PointSize="18">
    				<Properties>
    					<AppliedFont type="string">Times New Roman</AppliedFont>
    				</Properties>
    				<Content>%name%</Content>
    			</CharacterStyleRange>
    		</ParagraphStyleRange>
    	</Story>
    </idPkg:Story>
    Hier ist das "source.xml" mit dem einzusetzenden Wert:

    HTML Code:
    <name>Max Mustermann</name>
    Hier das XSL, dass anstelle von %name% den Wert Max Mustermann einsetzt:

    HTML Code:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output method="xml" indent="yes"/>
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
        </xsl:template>
        
        <xsl:variable name="insertIn">
            <xsl:text>/Users/max/Desktop/switch_test/source.xml</xsl:text>
        </xsl:variable>
        <xsl:variable name="insertion">
            <xsl:value-of select="document($insertIn)//name"/>
        </xsl:variable>
        
        <xsl:template match="Content[.='%name%']">
            <xsl:element name="Content">
                <xsl:value-of select="$insertion" />
            </xsl:element>
        </xsl:template>
    </xsl:stylesheet>
    Mein Ziel ist es nun die "source.xml" zu erweitern, so dass die XSL-Datei allgemeingültig bleiben kann und aus der Source der zu ersetzende Marker mit seinem neuen Wert stehen kann. Davon evtl. auch mehrere. Dieser Code hier funktioniert nicht, da man bei "template match" keine Variablen angeben kann.

    die neue "source.xml":
    HTML Code:
    <story>
        <replace regex="%name%">Max Mustermann</replace>
    </story>
    die veränderte XSL-Datei:

    HTML Code:
    <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
        <xsl:output method="xml" indent="yes"/>
        <xsl:template match="@* | node()">
            <xsl:copy>
                <xsl:apply-templates select="@* | node()"/>
            </xsl:copy>
        </xsl:template>
        <xsl:variable name="insertFrom">
            <xsl:text>/Users/max/Desktop/switch_test/source.xml</xsl:text>
        </xsl:variable>
        <xsl:variable name="replaceThis">
            <xsl:value-of select="document($insertFrom)/story/@regex"/>
        </xsl:variable>
        <xsl:variable name="insertThis">
            <xsl:value-of select="document($insertFrom)/story/replace"/>
        </xsl:variable>
        <xsl:template match="Content[.='$replaceThis']">
            <xsl:element name="Content">
                <xsl:value-of select="$insertThis" />
            </xsl:element>
        </xsl:template>
    </xsl:stylesheet>
    Kann mir jemand sagen, wie ich das Problem umschiffen kann. Ich habe schon ne Weile gesucht und bin schon froh, dass Variante 1 funktioniert. Danke

    Gruss
    Dom

  • #2
    Nimm einen XSLT 2.0 Prozessor wie Saxon 9, AltovaXML oder XQSharp, dann sind mit XSLT 2.0 auch Referenzen auf Variablen in match-Pattern erlaubt, also dann funktioniert
    Code:
    <xsl:template match="Content[. = $replaceThis]">...</xsl:template>
    So du das wirklich mit XSLT 1.0 machen willst, dann etwa
    Code:
    <xsl:template match="Content">
      <xsl:choose>
         <xsl:when test=". = $replaceThis">
            <xsl:copy>
               <xsl:value-of select="$insertThis"/>
            </xsl:copy>
          </xsl:when>
          <xsl:otherwise>
             <xsl:copy-of select="."/>
          </xsl:otherwise>
      </xsl:choose>
    </xsl:template>

    Comment


    • #3
      Danke Martin,

      das mit XSLT 2 wusste ich nicht. Ich habe gerade alles umgestellt und nun läufts.

      Gruss
      Dom

      Comment


      • #4
        XSLT auf externe Eingabe anwenden

        Hallo,

        ich muss nochmal nachhaken, weil die Sachlage sich verändert hat. Zunächst bin ich an XSLT 1.0 gebunden (gelöst!!!) und die Eingabe ist nun nicht mehr die zu verarbeitende Datei, sondern eine Steuerdatei:

        insert.xml:
        HTML Code:
        <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
        <root>
            <story file="Story_u4780.xml">
                <replace regex="%%%EMPFAENGER%%%">Max Mustermann</replace>
            </story>
            [...]
        </root>
        XSL:
        HTML Code:
        <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
            <xsl:output method="xml" indent="yes"/>
            <xsl:template name="replace">
                <xsl:param name="string"/>
                <xsl:param name="from"/>
                <xsl:param name="to"/>
                <xsl:choose>
                    <xsl:when test="contains($string, $from)">
                        <xsl:value-of select="substring-before($string, $from)"/>
                        <xsl:copy-of select="$to"/>
                        <xsl:call-template name="replace">
                            <xsl:with-param name="string" select="substring-after($string, $from)"/>
                            <xsl:with-param name="from" select="$from"/>
                            <xsl:with-param name="to" select="$to" />
                        </xsl:call-template>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="$string" />
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:template>
            <xsl:variable name="source">
                <xsl:text>/Users/admin/Desktop/inserts/insert.xml</xsl:text>
            </xsl:variable>
            <xsl:variable name="target">
                <xsl:text>/Users/admin/Desktop/source/Stories/</xsl:text>
                <xsl:value-of select="document($source)/root/story[1]/@file"/>
            </xsl:variable>
            <xsl:variable name="replaceThis">
                <xsl:value-of select="document($source)/root/story[1]/replace/@regex"/>
            </xsl:variable>
            <xsl:variable name="insertThis">
                <xsl:value-of select="document($source)/root/story[1]/replace"/>
            </xsl:variable>
            <xsl:template match="node()|@*">
                <xsl:copy>
                    <xsl:apply-templates select="node()|@*"/>
                </xsl:copy>
            </xsl:template>
            <xsl:template match="Content">
                <xsl:call-template name="replace">
                    <xsl:with-param name="string" select="."/>
                    <xsl:with-param name="from" select="$replaceThis"/>
                    <xsl:with-param name="to" select="$insertThis" />
                </xsl:call-template>
            </xsl:template>
        </xsl:stylesheet>
        Wie schaffe ich es, dass die Transformation auf das Dokument mit der Variable "target" angewendet wird. Ich habe folgendes mit "document()" versucht, dass erzeugt aber eine Schleife.

        <xsl:apply-templates select="document($target)/node()|@*"/>

        Danke
        Dominik

        Comment


        • #5
          Mit
          Code:
          <xsl:template match="/">
            <xsl:apply-templates select="document($target)/node()"/>
          </xsl:template>
          kannst du erreichen, dass die Kindknoten des target-Dokumentes verarbeitet werden.

          Comment

          Working...
          X