1

我有以下代码,如果有一个 orderEvents 元素并且该元素有一个不是 orderEvent 或空文本的子节点,它应该添加一个错误。测试用例更好地展示了我所追求的。

orderEventsXPATH 表达式在所有情况下都有效,除非元素中有空白区域。请参阅下面的测试用例validVendorPaymentFormat7。这是我的 XPATH 表达式。

"./expectedVendorPaymentTransactions/orderEvents/node()[not(self::orderEvent) or self::text()[normalize-space(.)!='']]"

测试用例:

<TestData>
  <TestcaseList>
    <Testcase>
      <rootIdentifier>validVendorPaymentFormat1</rootIdentifier>
      <expectedVendorPaymentTransactions>
        <orderEvents></orderEvents>
      </expectedVendorPaymentTransactions>
    </Testcase>
    <Testcase>
      <rootIdentifier>validVendorPaymentFormat2</rootIdentifier>
    </Testcase>
    <Testcase>
      <rootIdentifier>validVendorPaymentFormat3</rootIdentifier>
      <expectedVendorPaymentTransactions>
      </expectedVendorPaymentTransactions>
    </Testcase>
    <Testcase>
      <rootIdentifier>validVendorPaymentFormat4</rootIdentifier>
      <expectedVendorPaymentTransactions>
        <orderEvents><orderEvent>SOME_EVENT</orderEvent></orderEvents>
      </expectedVendorPaymentTransactions>
    </Testcase>
     <Testcase>
      <rootIdentifier>validVendorPaymentFormat5</rootIdentifier>
      <expectedVendorPaymentTransactions>
        <orderEvents><orderEvent>SOME_EVENT</orderEvent></orderEvents>
      </expectedVendorPaymentTransactions>
    </Testcase>
    <Testcase>
      <rootIdentifier>validVendorPaymentFormat6</rootIdentifier>
      <expectedVendorPaymentTransactions>
        <orderEvents><orderEvent>SOME_EVENT</orderEvent><orderEvent>SOME_EVENT</orderEvent></orderEvents>
      </expectedVendorPaymentTransactions>
    </Testcase>
    <Testcase>
      <rootIdentifier>validVendorPaymentFormat7</rootIdentifier>
      <expectedVendorPaymentTransactions>
        <orderEvents>
          <orderEvent>SOME_EVENT</orderEvent>
        </orderEvents>
      </expectedVendorPaymentTransactions>
    </Testcase>
  </TestcaseList>
</TestData>

失败的案例是validVendorPaymentFormat7

失败消息:

[exec] Failure:
 [exec]   Order vendor payments format contains elements other than orderEvent for validVendorPaymentFormat7 ["\n          ", "\n        "].
 [exec]   <false> is not true.

将失败案例更改为:

        <Testcase>
          <rootIdentifier>validVendorPaymentFormat7</rootIdentifier>
          <expectedVendorPaymentTransactions>
            <orderEvents><orderEvent>SOME_EVENT</orderEvent></orderEvents>
          </expectedVendorPaymentTransactions>
        </Testcase>

结果通过。

不幸的是,在http://www.freeformatter.com/xpath-tester.html测试用例 #7 按预期返回一个空列表。

更新 - 添加代码
Ruby 版本:1.9
irb -v = 0.9.6

测试文件:

require 'rexml/document'

xpath = "//expectedVendorPaymentTransactions/orderEvents/node()[not(self::orderEvent) or self::text()[translate(., ' &#10;', '')!='']]"
document = REXML::Document.new <<EOF 
    <Testcase>
      <rootIdentifier>validVendorPaymentFormat7</rootIdentifier>
      <expectedVendorPaymentTransactions>
        <orderEvents>
          <orderEvent>SOME_EVENT</orderEvent>
        </orderEvents>
      </expectedVendorPaymentTransactions>
    </Testcase>
EOF

document2 = REXML::Document.new <<EOF 
    <Testcase>
      <rootIdentifier>validVendorPaymentFormat7</rootIdentifier>
      <expectedVendorPaymentTransactions>
        <orderEvents><orderEvent>SOME_EVENT</orderEvent></orderEvents>
      </expectedVendorPaymentTransactions>
    </Testcase>
EOF

puts "1: #{REXML::XPath.match(document, xpath).inspect}"
puts "2: #{REXML::XPath.match(document2, xpath).inspect}"

输出:

irb(main):001:0> load './test/test_rexp.rb'
1: ["\n          ", "\n        "]
2: []
=> true

Jens 的最新版本:

irb(main):009:0> load './test/test_rexp.rb'
1: ", "
2: ", "
=> true
4

2 回答 2

1

似乎 Ruby 没有将换行符作为normalize-space(...). 如果它包含除空格以外的任何内容,您会感兴趣,因此只需删除所有空格。translate(...)可以派上用场。第一个参数是您要匹配的内容,第二个字符串是要匹配的内容,第三个参数是要替换的字符;因为它是空的,所以所有匹配的字符都将被删除。

translate(., ' &#10;', '')

我可以用 Perl 的 XPath 重现该问题,并通过以下查询解决:

/expectedVendorPaymentTransactions/orderEvents/node()[not(self::orderEvent) or self::text()[translate(., ' &#10;', '')!='']]

更新:Ruby 似乎无法正确解析 XML 实体,但您可以使用\n换行符:

translate(., ' \n', '')
于 2013-09-24T07:28:14.617 回答
1

从 XPATH 中删除空格处理并使用相当简单的 ruby​​ 解决方法。

工作代码:

require 'rexml/document'
require 'rexml/text'

xpath = "//expectedVendorPaymentTransactions/orderEvents/node()[not(self::orderEvent)]"
document = REXML::Document.new <<EOF 
    <Testcase>
      <rootIdentifier>validVendorPaymentFormat7</rootIdentifier>
      <expectedVendorPaymentTransactions>
        <orderEvents>
          <orderEvent>Fulfill</orderEvent>
        </orderEvents>
      </expectedVendorPaymentTransactions>
    </Testcase>
EOF

document2 = REXML::Document.new <<EOF 
    <Testcase>
      <rootIdentifier>validVendorPaymentFormat7</rootIdentifier>
      <expectedVendorPaymentTransactions>
        <orderEvents><orderEvent>Fulfill</orderEvent></orderEvents>
      </expectedVendorPaymentTransactions>
    </Testcase>
EOF

elements = REXML::XPath.match(document, xpath)
elements.reject! { |element| 
      element.instance_of?(REXML::Text) and element.value.gsub(/[\n ]/,"") == ''
    }
puts "1: #{elements.inspect}"

elements2 = REXML::XPath.match(document2, xpath)
elements2.reject! { |element| 
      element.instance_of?(REXML::Text) and element.value.gsub(/[\n\t ]/,"") == ''
    }
puts "2: #{elements2.inspect}"
于 2013-09-26T21:08:55.350 回答