代码之家  ›  专栏  ›  技术社区  ›  Kris Van den Bergh

实际上是XSLT查找(在循环期间存储变量,并在其中使用另一个模板)

  •  0
  • Kris Van den Bergh  · 技术社区  · 15 年前

    这个问题实际上提出了一些非常不同的问题 . 查看对@tomalak答案的评论,了解OP真正想要的是什么。:(

    是否有一种方法可以在for each循环期间将变量/参数存储在一种数组中,并在另一个模板中使用它,即 <xsl:template match="Foundation.Core.Classifier.feature"> . 所有的 classname 应存储在for each期间出现的值。您将如何在XSLT中实现它?这是我目前的密码。

    <xsl:for-each select="Foundation.Core.Class">       
     <xsl:for-each select="Foundation.Core.ModelElement.name">
      <xsl:param name="classname">
       <xsl:value-of select="Foundation.Core.ModelElement.name"/>
      </xsl:param>
     </xsl:for-each>
     <xsl:apply-templates select="Foundation.Core.Classifier.feature" /> 
    </xsl:for-each>
    

    这是模板,其中 类的名称 应使用参数。

    <xsl:template match="Foundation.Core.Classifier.feature">
     <xsl:for-each select="Foundation.Core.Attribute">
      <owl:DatatypeProperty rdf:ID="{Foundation.Core.ModelElement.name}">
       <rdfs:domain rdf:resource="$classname" />
      </owl:DatatypeProperty>
     </xsl:for-each>
    </xsl:template>
    

    输入文件位于 http://krisvandenbergh.be/uml_pricing.xml

    2 回复  |  直到 15 年前
        1
  •  5
  •   Community CDub    8 年前

    不,不可能在for each循环中存储变量,然后再使用它。

    这是因为变量在XSLT中只写一次(一旦设置,它们就不可变),并且它们在其父元素中有严格的作用域。一旦处理离开for each循环,变量就消失了。

    XSLT并不是一种命令式编程语言,但这正是您在这里尝试的。你不需要 <xsl:for-each> 在98%的情况下,不应该使用它,因为它会阻塞您对XSLT工作方式的看法。为了改进您的XSLT代码,去掉所有 <xsl:每个> 您拥有的循环(所有循环,我的意思是它),使用模板代替:

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

    (我不确定以上是否是你真正想要的,你的问题相当含糊。)

    注意xpath的用法 ancestor 轴引用层次结构中较高的元素(您似乎希望 <Foundation.Core.ModelElement.name> 父类的)。

    PS:由于结构化的元素名,您的XML非常膨胀,而且非常冗余。结构应该来自…好。。。 结构 不是来自像 <Foundation.Core.Classifier.feature> . 不过,我不确定你是否能做些什么。


    添加:

    解决你的问题 xmi.id / xmi.idref 问题是,最好的方法是使用XSL密钥:

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

    为了更好地理解密钥的内部工作方式,您可以阅读 this answer I gave earlier . 不要为这个问题操心太多,只要看我答案的下半部分,我用JavaScript解释了键。

        2
  •  -1
  •   Kris Van den Bergh    15 年前

    好吧,我现在明白为什么了 for-each 并不总是需要的。考虑下面的代码。

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

    它有身份证 UID71848B1D-2741-447E-BD3F-BD606B7FD29E

    在其他地方,我有以下内容。

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

    如您所见,两个代码都有相同的ID。现在我想输出“int”,每次这个ID出现在文档的某个地方。所以基本上 idref="UID71848B1D-2741-447E-BD3F-BD606B7FD29" 应替换为 int ,可以很容易地从 Foundation.Core.ModelElement.name 元素。

    上面是我希望将其存储在变量中的主要原因。我不明白如何使用XSLT来处理这个问题。如果有人能详细阐述这个问题,我希望有某种模式可以解决这个问题,因为我经常需要它。什么是好方法?

    我知道这可能有点离题,但我还是愿意在这篇文章中问它,因为这个问题非常接近它。

    推荐文章