2017-06-09 5 views
1

ist folgender Code Bitte beachten Sie:XSLT: XPath-Abfrage mit erweitertem Wert gibt „Knoten vorhanden ist“, wenn kein solcher Knoten vorhanden

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format"> 
    <xsl:template name="getServiceDef"> 
     <services> 
      <service> 
       <serviceName>service</serviceName> 
       <parameters> 
        <param1/> 
        <param2/> 
        <param3/> 
       </parameters> 
      </service> 
     </services> 
    </xsl:template> 

    <xsl:template name="getInput"> 
     <parameters> 
      <param1>10</param1> 
      <param2>single</param2> 
      <param3>2</param3> 
      <param4>650</param4> 
      <param5>750</param5> 
     </parameters> 
    </xsl:template> 

    <xsl:template match="/"> 
     <xsl:variable name="serviceDef"> 
      <xsl:call-template name="getServiceDef"/> 
     </xsl:variable> 
     <xsl:variable name="inputParameters"> 
      <xsl:call-template name="getInput"/> 
     </xsl:variable> 

     <xsl:for-each select="$inputParameters/parameters/param4"> 
      <xsl:variable name="currentParameterName" select="./local-name()"/> 
      <xsl:choose> 
       <xsl:when test="$serviceDef/services/service/parameters/$currentParameterName"> 
        <xsl:message> 
         $currentParameterName '<xsl:value-of select="$currentParameterName"/>'exists. 
         $serviceDef/services/service/parameters/param4 '<xsl:value-of select="$serviceDef/services/service/parameters/param4"/>' 
         $serviceDef/services/service/parameters/$currentParameterName '<xsl:value-of select="$serviceDef/services/service/parameters/$currentParameterName"/>' 
        </xsl:message> 
       </xsl:when> 
       <xsl:otherwise> 
        <xsl:message>param '<xsl:value-of select="$currentParameterName"/>' does NOT exist</xsl:message> 
       </xsl:otherwise> 
      </xsl:choose> 
     </xsl:for-each> 
    </xsl:template> 
</xsl:stylesheet> 

In Codeblock beginnend mit Zeile

<xsl:for-each select="$inputParameters/parameters/param4"> 

Ich versuche, zu entscheiden, ob der Knoten auch in $ serviceDef existiert. Es tut nicht. Wenn die XPATH-Abfrage jedoch mit einer expandierten Variablen ausgeführt wird, wird die Abfrage als "Knoten existiert" (Konsolenausgabe unten) ausgewertet.

Frage: Warum Abfrage $ serviceDef/services/service/Parameter/param4 "False" und $ serviceDef/services zurück/service/Parameter/$ currentParameterName gibt "True"? Ich würde erwarten, dass Abfragen identisch sind.

So zu replizieren: ~ $ echo "< notneeded/>"> sample.xml

  • Laptop:

    1. oben Code kopieren stackOverFlowReplication.xsl

    2. Laptop Datei ~ $ java -jar saxon9pe.jar -s: beispiel.xml -xsl: stackOverFlowReplication.xsl

    Console Ausgabe:

    No license file found - running with licensable features disabled 
    Warning at xsl:stylesheet on line 2 column 125 of stackOverFlowReplication.xsl: 
        Running an XSLT 10 stylesheet with an XSLT 20 processor 
    
         $currentParameterName 'param4'exists. 
         $serviceDef/services/service/parameters/param4 '' 
         $serviceDef/services/service/parameters/$currentParameterName 'param4' 
    
  • Antwort

    1

    Sie scheinen zu erwarten, dass test="$serviceDef/services/service/parameters/$currentParameterName" einen XPath-Ausdruck zur Laufzeit konstruiert, basierend auf Ihren Variable in diesem letzten Schritt eingefügt. Das passiert nicht, Sie werten im letzten Schritt einfach die Variablenreferenz $currentParameterName aus, und sie wertet die Zeichenfolge param4 aus, und alle nicht leeren Strings im booleschen Kontext wie xsl:when/xsl:if test werden als wahr ausgewertet.

    Sie müssen entweder in XSLT 3.0 für dynamische XPath Auswertung verwenden oder für Ihren einfachen Fall können Sie z. test="$serviceDef/services/service/parameters/*[local-name() = $currentParameterName]".

    Sie eine Vorstellung davon zu geben, was Ihr Ausdruck auswertet, um http://xsltransform.net/naZXpX1 zu sehen, die

    <xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" xmlns:xs="http://www.w3.org/2001/XMLSchema" 
        exclude-result-prefixes="xs fo"> 
        <xsl:template name="getServiceDef"> 
         <services> 
          <service> 
           <serviceName>service</serviceName> 
           <parameters> 
            <param1/> 
            <param2/> 
            <param3/> 
           </parameters> 
          </service> 
         </services> 
        </xsl:template> 
    
        <xsl:template name="getInput"> 
         <parameters> 
          <param1>10</param1> 
          <param2>single</param2> 
          <param3>2</param3> 
          <param4>650</param4> 
          <param5>750</param5> 
         </parameters> 
        </xsl:template> 
    
        <xsl:template match="/"> 
         <xsl:variable name="serviceDef"> 
          <xsl:call-template name="getServiceDef"/> 
         </xsl:variable> 
         <xsl:variable name="inputParameters"> 
          <xsl:call-template name="getInput"/> 
         </xsl:variable> 
    
         <xsl:for-each select="$inputParameters/parameters/param4"> 
          <xsl:variable name="currentParameterName" select="./local-name()"/> 
          <xsl:variable name="exp1" select="$serviceDef/services/service/parameters/$currentParameterName"/> 
          <debug-help string-sequence-test="{$exp1 instance of xs:string*}" node-sequence-test="{$exp1 instance of node()*}" value="{$exp1}"/> 
    
         </xsl:for-each> 
        </xsl:template> 
    </xsl:stylesheet> 
    

    tut die Ausgänge <debug-help string-sequence-test="true" node-sequence-test="false" value="param4"/> so zeigt es Sie nie eine Knotensequenz haben, sondern einfach eine Folge von einer einzigen Saite mit dem variabler Wert

    +0

    Sie haben Recht, ich erwartete genau das Verhalten, das Sie beschrieben haben. Es ist mir nicht in den Sinn gekommen, dass ich eine variable Referenz tatsächlich auswerte. Vielen Dank für die Erklärung, es macht Sinn. Da ich gezwungen bin, XSLT 1.0 zu verwenden, verwende ich das von Ihnen bereitgestellte Beispiel. Nochmals vielen Dank für die schnelle und korrekte Antwort. – Boris

    +0

    Wenn Sie XSLT 1.0 verwenden, sollten Sie einen XSLT 1.0-Prozessor verwenden, um Ihren Code zu testen, da '$ serviceDef/services/service/parameters/$ currentParameterName' nicht einmal syntaktisch funktioniert, sondern Ihnen einen Syntaxfehler gibt. –

    +0

    Danke für den guten Punkt Martin, ich werde es mir merken. – Boris

    Verwandte Themen