Actually XSLT Lookup (Store variables during loop and use in it another template)

后端 未结 2 1590
眼角桃花
眼角桃花 2020-12-22 12:39

This question actually asks something quite different. See the comments to @Tomalak\'s answer to understand what the OP really wanted. :(

Is there a

相关标签:
2条回答
  • 2020-12-22 13:07

    No, it is not possible to store a variable in a for-each loop and use it later.

    This is because variables are write-once in XSLT (once set they are immutable) and they are strictly scoped within their parent element. Once processing leaves the for-each loop, the variable is gone.

    XSLT does not work as an imperative programming language, but that's what you seem to be trying here. You don't need <xsl:for-each> in 98% of all cases and should not use it because it clogs your view of how XSLT works. To improve your XSLT code, get rid of all <xsl:for-each> loops you have (all of them, I mean it) and use templates instead:

    <xsl:template match="Foundation.Core.Class">
      <xsl:apply-templates select="
        Foundation.Core.Classifier.feature/Foundation.Core.Attribute
      " />
    </xsl:template>
    
    <xsl:template match="Foundation.Core.Attribute">
      <owl:DatatypeProperty rdf:ID="{Foundation.Core.ModelElement.name}">
        <rdfs:domain rdf:resource="{
          ancestor::Foundation.Core.Class[1]/Foundation.Core.ModelElement.name[1]
        }" />
      </owl:DatatypeProperty>
    </xsl:template>
    

    (I'm not sure if the above is what you actually want, your question is rather ambiguous.)

    Note the use of the XPath ancestor axis to refer to an element higher in the hierarchy (you seem to want the <Foundation.Core.ModelElement.name> of the parent class).

    PS: Your XML is incredibly bloated and strongly redundant due to structured element names. Structure should come from... well... structure, not from elements like <Foundation.Core.Classifier.feature>. I'm not sure if you can do anything about it, though.


    Addition:

    To solve your xmi.id / xmi.idref problem, the best way is to use an XSL key:

    <!-- this indexes all elements by their @xmi.id attribute -->
    <xsl:key name="kElementByIdref" match="*[@xmi.id]" use="@xmi.id" />
    
    <!-- now you can do this -->
    <xsl:template match="Foundation.Core.DataType">
      <dataTypeName>
       <!-- pull out the corresponding element from the key, output its value -->
       <xsl:value-of select="key('kElementByIdref', @xmi.idref)" />
      </dataTypeName>
    </xsl:template>
    

    To better understand how keys work internally, you can read this answer I gave earlier. Don't bother too much with the question, just read the lower part of my answer, I explained keys in terms of JavaScript.

    0 讨论(0)
  • 2020-12-22 13:15

    Ok, I now understand why for-each is not always needed. Consider the code below.

    <Foundation.Core.DataType xmi.id="UID71848B1D-2741-447E-BD3F-BD606B7FD29E">
    <Foundation.Core.ModelElement.name>int</Foundation.Core.ModelElement.name>
    </Foundation.Core.DataType>
    

    It has an id UID71848B1D-2741-447E-BD3F-BD606B7FD29E

    Way elsewhere I have the following.

        <Foundation.Core.StructuralFeature.type>
    <Foundation.Core.DataType xmi.idref="UID71848B1D-2741-447E-BD3F-BD606B7FD29E"/>
    </Foundation.Core.StructuralFeature.type>
    

    As you can see, both codes have the same ID. Now I want to output "int", everytime this ID appears somewhere in the document. So basically idref="UID71848B1D-2741-447E-BD3F-BD606B7FD29" should be replaced by int, which can be easily derived from the Foundation.Core.ModelElement.name element.

    Above is the main reason why I would like to store it in a variable. I don't get it how this can be dealt with using XSLT. If someone could elaborate on this, I hope there exists some kind of pattern to solve such a problem, since I need it quite often. What would be a good approach?

    I understand this is maybe a bit off-topic, but I am willing to ask it in this thread anyway since this problem is very close to it.

    0 讨论(0)
提交回复
热议问题