2

项目的属性在@properties 属性中作为空格分隔的术语列出。还有一个属性的主列表。

<t>

   <items>
     <item id='a' properties='red little' />
     <item id='b' properties='big strong heavy' />
     <item id='c' properties='blue heavy' >
   </items>

   <properties>
     <property id='red' />
     <property id='little' />
     <property id='blue' />
   </properties>

</t>

我的问题:使用 XLST 1.0,为模板编写一个匹配属性,该属性将匹配在属性主列表中至少具有一个属性的所有项目。

项目 a 和 c 将匹配。b项不会。

它是 XSLT 1.0,所以我不能使用 str:split。也许带有键和包含()的东西?

4

3 回答 3

1

你也可以用<xsl:if>吗?

<xsl:template match="item">
    <xsl:if test="/t/properties/property[contains(concat(' ', current()/@properties, ' '), concat(' ', @id, ' '))]">
        ...
    </xsl:if>
</xsl:template>

不幸的是,current()不能在match属性内使用。

于 2012-12-25T21:15:35.683 回答
1

使用 Michael Liu 的 XPath 表达式,您还可以构造一个键来匹配正确的元素:

<xsl:key name="inMaster" match="item" use="
    substring(
      '1',
      1,
      string-length(
        /t/properties/property[
          contains(concat(' ', current()/@properties, ' '), concat(' ', @id, ' '))
        ]/@id
      )
    )"/>

<!-- The following template matches the wanted item elements -->
<xsl:template match="key('inMaster','1')">
  ...
</xsl:template>

我们使用该substring()函数将匹配<item>元素与字符串相关联"1"。所有不匹配的 item 元素都与空字符串相关联,因为没有匹配的“master”属性,因此没有id属性,因此string-length()为 0,因此我们提取长度为 0 的子字符串(即空字符串)。

于 2012-12-25T22:39:35.997 回答
1

I. 使用键和current():)的另一种解决方案:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>

 <xsl:key name="kItemByProp" match="item"
  use="boolean(/*/properties/property/@id
                 [contains(concat(' ', current()/@properties, ' '),
                           .)]
              )"/>

 <xsl:template match=
  "item[count(.| key('kItemByProp', 'true'))
       =
        count(key('kItemByProp', 'true'))
        ]
  ">
  <xsl:copy-of select="."/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于提供的 XML 文档时:

<t>
    <items>
        <item id='a' properties='red little' />
        <item id='b' properties='big strong heavy' />
        <item id='c' properties='blue heavy' />
    </items>
    <properties>
        <property id='red' />
        <property id='little' />
        <property id='blue' />
    </properties>
</t>

产生了想要的正确结果:

<item id="a" properties="red little"/>
<item id="c" properties="blue heavy"/>

二、没有键,但有一个条件指令作为模板主体的最外层:

 <xsl:template match="item">
  <xsl:if test=
  "/*/properties/*/@id
        [contains(concat(' ', current()/@properties, ' '), .)]">
    <!-- Your processing here -->
  </xsl:if>
 </xsl:template>

这是一个完整的转换:

<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:template match="item">
  <xsl:if test=
  "/*/properties/*/@id
        [contains(concat(' ', current()/@properties, ' '), .)]">
    <xsl:copy-of select="."/>
  </xsl:if>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于同一个 XML 文档(如上)时,会产生相同的正确结果

<item id="a" properties="red little"/>
<item id="c" properties="blue heavy"/>
于 2012-12-25T22:58:45.020 回答