加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby – 选择相邻的兄弟元素,而不插入非空白文本节点

发布时间:2020-12-17 03:36:00 所属栏目:百科 来源:网络整理
导读:给定标记如: p codefoo/codecodebar/code codejim/code and then codejam/code/p 我需要选择前三个 code – 但不是最后一个.逻辑是“选择具有先前或后续兄弟元素的所有代码元素,该元素也是代码,除非存在一个或多个文本节点,它们之间具有非空白内容. 鉴于我
给定标记如:

<p>
  <code>foo</code><code>bar</code>
  <code>jim</code> and then <code>jam</code>
</p>

我需要选择前三个< code> – 但不是最后一个.逻辑是“选择具有先前或后续兄弟元素的所有代码元素,该元素也是代码,除非存在一个或多个文本节点,它们之间具有非空白内容.

鉴于我正在使用Nokogiri(使用libxml2),我只能使用XPath 1.0表达式.

虽然需要一个棘手的XPath表达式,但是在Nokogiri文档上执行相同操作的Ruby代码/迭代也是可以接受的.

请注意,CSS adjacent sibling selector会忽略非元素节点,因此选择nokodoc.css(‘code code’)会错误地选择最后一个< code>块.

Nokogiri.XML('<r><a/><b/> and <c/></r>').css('* + *').map(&:name)
#=> ["b","c"]

编辑:更多测试用例,为清楚起见:

<section><ul>
  <li>Go to <code>N</code> and
      then <code>Y</code><code>Y</code><code>Y</code>.
  </li>
  <li>If you see <code>N</code> or <code>N</code> then…</li>
</ul>
<p>Elsewhere there might be: <code>N</code></p>
<p><code>N</code> across parents.</p>
<p>Then: <code>Y</code> <code>Y</code><code>Y</code> and <code>N</code>.</p>
<p><code>N</code><br/><code>N</code> elements interrupt,too.</p>
</section>

应选择上面的所有Y.不应该选择N. < code>的内容仅用于指示应选择哪个:您可以不使用内容来确定是否选择元素.

其中< code>的上下文元素出现是无关紧要的.它们可能出现在< li>中,它们可能出现在< p>中,它们可能出现在其他内容中.

我想选择< code>的所有连续运行立刻.在一组Y中间有一个空格字符并不是错误.

解决方法

使用:

//code
     [preceding-sibling::node()[1][self::code]
    or
      preceding-sibling::node()[1]
         [self::text()[not(normalize-space())]]
     and
      preceding-sibling::node()[2][self::code]
    or
     following-sibling::node()[1][self::code]
    or
      following-sibling::node()[1]
         [self::text()[not(normalize-space())]]
     and
      following-sibling::node()[2][self::code]
     ]

基于XSLT的验证:

<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="/">
      <xsl:copy-of select=
       "//code
             [preceding-sibling::node()[1][self::code]
            or
              preceding-sibling::node()[1]
                 [self::text()[not(normalize-space())]]
             and
              preceding-sibling::node()[2][self::code]
            or
             following-sibling::node()[1][self::code]
            or
              following-sibling::node()[1]
                 [self::text()[not(normalize-space())]]
             and
              following-sibling::node()[2][self::code]
             ]"/>
     </xsl:template>
</xsl:stylesheet>

在提供的XML文档上应用此转换时:

<section><ul>
      <li>Go to <code>N</code> and
          then <code>Y</code><code>Y</code><code>Y</code>.
      </li>
      <li>If you see <code>N</code> or <code>N</code> then…</li>
    </ul>
    <p>Elsewhere there might be: <code>N</code></p>
    <p><code>N</code> across parents.</p>
    <p>Then: <code>Y</code> <code>Y</code><code>Y</code> and <code>N</code>.</p>
    <p><code>N</code><br/><code>N</code> elements interrupt,too.</p>
</section>

计算包含的XPath表达式,并将选定的节点复制到输出:

<code>Y</code>
<code>Y</code>
<code>Y</code>
<code>Y</code>
<code>Y</code>
<code>Y</code>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读