xsl - 在父级中混合文本的标记位置

时间:2011-04-09 15:48:37

标签: xml xslt xslt-1.0

在XSL 1.0中,我试图区分以下两种情况,这两种情况都发生在我需要处理的输入XML中,并且每种情况都要以不同方式处理。

情景1

<tag1><tag2/> some text</tag1>

情景2

<tag1>some text <tag2/></tag1>

我有一个匹配<tag2/>级别的模板,在此我想要的方案1中忽略<tag2/>,在方案2中我想插入<br/>代替{{ 1}}。

我在这里和谷歌搜索过,但似乎无法根据<tag2/><tag2/>的位置找出如何区分。

我调查了前兄弟 generate-id ,并试图使用类似的内容: -

<tag1>

 not(
    generate-id(
       preceding-sibling::node()[1]
    )
  = generate-id(
       preceding-sibling::text()[1]
    )
 )
position()

似乎没有帮助,因为两者似乎都在节点级别运行?

欢迎任何想法?

由于 罗杰

3 个答案:

答案 0 :(得分:1)

查看这些模式

node()[1]

匹配第一个节点子节点。

node()[1][self::tag2]

此匹配第一个节点子节点,也是tag2元素。

node()[not(self::text()[not(normalize-space())])][1][self::tag2]

匹配第一个节点子节点,它不是仅空白文本节点,也是tag2元素(如果您使用XHTML输入保留空白,则只保留文本节点)。

我给你这种方法,因为第一和第二个模式是streamablepreceding轴不可流动)。

注意:第二个必须重写为node()[position() = 1 and self::tag2]

答案 1 :(得分:0)

以下样式表:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="tag2[preceding-sibling::text()]">
        <br/>
    </xsl:template>
</xsl:stylesheet>

在此输入上:

<items>
    <tag1><tag2/>some text</tag1>
    <tag1>some text <tag2/></tag1>
</items>

产地:

some text
some text <br/>

更复杂的解决方案需要有关所需输出的其他信息。

答案 2 :(得分:0)

更简单,更基本的解决方案

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

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

 <xsl:template match=
  "node()[self::tag2 and position()=1]"/>
 <xsl:template match=
  "node()[self::tag2 and position()=2]">
  <br/>
 </xsl:template>
</xsl:stylesheet>

应用于此XML文档

<tag1><tag2/> some text</tag1>

会产生想要的正确结果:

<tag1> some text</tag1>

应用于此文档时

<tag1>some text <tag2/></tag1>

再次生成想要的正确答案

<tag1>some text <br/>
</tag1>

<强>解释

  1. 标识规则(模板)按原样复制每个节点。

  2. 覆盖标识规则的第一个模板匹配名称为tag2且节点列表中的位置为1的任何节点。它没有正文,因此tag2元素是忽略。

  3. 覆盖标识规则的第二个模板与第一个类似,但匹配的tag2节点的位置必须为2.在这种情况下,它将替换为<br/>