1

我有一堆文档,我正在尝试使用 xslt 设置样式,并且我有一些这样的代码:

<tag1>Something</tag1>
<tag2>Something else</tag2>
<tag3>...</tag3>

但在某些文件中可能只有:

<tag2>Something else</tag2>
<tag3>...</tag3>

当我渲染文档时,我想<h2>Heading</h2>在 tag1、tag2 或 tag3 之前添加一个“”(以先到者为准)。这可能吗?

4

5 回答 5

3

就这么简单(没有条件指令,没有xsl:element,没有starts-with(),没有preceding-sibling::轴,没有模式,只有一个覆盖标准身份规则的模板):

<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="node()|@*" name="identity">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

 <xsl:template match="*[self::tag1 or self::tag2 or self::tag3][1]">
   <h2>Heading</h2>
   <xsl:call-template name="identity"/>
 </xsl:template>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时(将提供的片段包装到单个顶部元素中以成为格式良好的 XML 文档):

<t>
    <tag1>Something</tag1>
    <tag2>Something else</tag2>
    <tag3>...</tag3>
</t>

产生了想要的正确结果:

<t>
   <h2>Heading</h2>
   <tag1>Something</tag1>
   <tag2>Something else</tag2>
   <tag3>...</tag3>
</t>

请注意

如果有很多元素名称(不一定以相同的字符串开头,那么像这样重写最后一个模板的匹配模式会更短更实用:

 <xsl:template match=
  "*[contains('|tag1|tag2|tag3|', concat('|',name(),'|'))][1]">
于 2012-11-08T04:42:55.753 回答
1
<xsl:if test="count(./preceding-sibling::*)=0"><h2>Heading</h2></xsl:if>

这意味着当前节点在文档中的前面有 0 个兄弟元素(即是其父节点的第一个元素)。但正如评论的那样:定位父元素并将 H2 添加到其输出中会产生更好的性能。

总是有一个包含标签,在最坏的情况下它是文档元素本身。

于 2012-11-08T01:36:33.600 回答
0

稍微不同的方法:

<xsl:template match="*[tag1|tag2|tag3]">
<xsl:element name="{name()}">
<h2>Heading</h2>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>

<xsl:template match="tag1|tag2|tag3">
<xsl:element name="{name()}"><xsl:apply-templates/></xsl:element>
</xsl:template>
于 2012-11-08T01:41:49.493 回答
0

这是我发现对我有用的东西:

<xsl:template match="*[starts-with(name(), 'tag')][1]" priority="1">
  <h2>Heading</h2>

  <xsl:apply-templates select="." mode="display"/>
</xsl:template>

<xsl:template match="*[starts-with(name(), 'tag')]">
  <xsl:apply-templates select="." mode="display"/>
</xsl:template>

<xsl:template match="root/tag1" mode="display">
  <p>First tag:
  <xsl:apply-templates />
  </p>
</xsl:template>

<xsl:template match="root/tag2" mode="display">
  <p>Second tag:
  <xsl:apply-templates />
  </p>
</xsl:template>

<xsl:template match="root/tag3" mode="display">
  <p>Third tag:
  <xsl:apply-templates />
  </p>
</xsl:template>

有点不正统,但效果很好。

于 2012-11-08T03:12:44.250 回答
0

这个 XSLT 1.0 样式表...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="@*|node()" name="ident">
  <xsl:copy>
     <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
</xsl:template>

<xsl:template match="*[self::tag1|self::tag2|self::tag3]
                      [not(preceding-sibling::tag1|
                           preceding-sibling::tag2|
                           preceding-sibling::tag3)]">
  <h2>Heading</h2>
  <xsl:call-template name="ident" />
</xsl:template>      
</xsl:stylesheet>

...或者等价于这个 XSLT 2.0 一个...

<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes" />
<xsl:strip-space elements="*" />

<xsl:template match="@*|node()">
  <xsl:copy>
     <xsl:apply-templates select="@*|node()" />
  </xsl:copy>
</xsl:template>

<xsl:template match="*[self::tag1|self::tag2|self::tag3]
                      [not(preceding-sibling::tag1|
                           preceding-sibling::tag2|
                           preceding-sibling::tag3)]">
  <h2>Heading</h2>
  <xsl:next-match />
</xsl:template>      
</xsl:stylesheet>

...将转换此输入文档..

<t>
  <branch1>
    <something-before/>
    <tag1>Something</tag1>
    <tag2>Something else</tag2>
    <tag3>tag3 content</tag3>
    <something-after/>
  </branch1>
  <branch2>
    <something-before/>
    <tag3>tag3 content</tag3>
    <tag2>Something else</tag2>
    <something-after/>
  </branch2>
</t>

...进入...

<t>
  <branch1>
    <something-before />
    <h2>Heading</h2>
    <tag1>Something</tag1>
    <tag2>Something else</tag2>
    <tag3>tag3 content</tag3>
    <something-after />
  </branch1>
  <branch2>
    <something-before />
    <h2>Heading</h2>
    <tag3>tag3 content</tag3>
    <tag2>Something else</tag2>
    <something-after />
  </branch2>
</t>
于 2012-11-08T04:42:32.003 回答