在第一个标签实例之前插入文本

时间:2012-11-08 01:19:05

标签: xml xslt

我有一堆文件,我正试图用xslt设置样式,我有一些像这样的代码:

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

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

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

当我渲染文档时,我想在tag1,tag2或tag3之前添加一个“<h2>Heading</h2>”(它首先出现)。这可能吗?

5 个答案:

答案 0 :(得分:2)

就这么简单(没有条件指令,没有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]">

答案 1 :(得分:1)

<xsl:if test="count(./preceding-sibling::*)=0"><h2>Heading</h2></xsl:if>

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

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

答案 2 :(得分: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>

答案 3 :(得分: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>

有点不正统,但它运作正常。

答案 4 :(得分: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>