【问题标题】:XPath 1.0 to find if an element's value is in a list of valuesXPath 1.0 查找元素的值是否在值列表中
【发布时间】:2010-06-11 20:08:02
【问题描述】:

有没有办法构造一个 XPath 来评估元素的值是否在预定义的值列表中?类似的东西:

/Location/Addr[State='TX or AL or MA']

哪个节点与德克萨斯州、阿拉巴马州或马萨诸塞州的州元素相匹配?我知道我可以解包表达式:

/Location/Addr[State='TX] or  /Location/Addr[State='AL'], etc...

但这有点麻烦,因为 xpath 很长,值列表也是如此。我的 google-fu 在这个问题上没有出现太多...

【问题讨论】:

    标签: list xpath expression


    【解决方案1】:

    您可以在同一个方括号内检查多个条件:

    /Location/Addr[State='TX' or State='AL' or State='MA']
    

    或者,如果您有一个很长的列表,您可以创建一个状态列表并使用contains() 函数。

    /Location/Addr[contains('TX AL MA', State)]
    

    这适用于两个字母的州缩写。如果您想让更长的字符串更加健壮,您可以在末尾添加一些空格并检查_TX__AL_ 等(下划线是空格)。

    /Location/Addr[contains(' TX AL MA ', concat(' ', State, ' '))]
    

    【讨论】:

      【解决方案2】:

      只是死灵,因为 XPath 2.0 已经出现。

      使用 XPath 2.0,您可以:

      /Location/Addr[State=('TX', 'AL', 'MA')]
      

      或者,在 XPath 1.0 中,您可以将 contains 与 string-length 结合使用:

      DECLARE @tXML xml = '<svg>
      <g>
      <path></path>
      <path data-objid="0000X1">tt</path>
      <path data-objid="0000X2"></path>
      <path data-objid="0000X3"></path>
      </g>
      </svg>';
      
      -- SELECT @tXML;
      
      SELECT 
          c.p.value('(@data-objid)[1]', 'varchar(50)') AS objID 
      FROM @tXML.nodes('//node()[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]') AS c(p)
      
      
      SET @tXML.modify('delete //node()[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]'); 
      
      SELECT @tXML AS del;
      
      DECLARE @newRecord xml = '<path data-objid="0000X4"></path>'; 
      
      
      -- SET @tXML.modify('insert sql:variable("@newRecord") as first into (/svg/g)[1]')
      SET @tXML.modify('insert sql:variable("@newRecord") as last into (/svg/g)[1]')
      
      SELECT @tXML AS ins;
      

      另见:add block into specific position

      而要更新(使用xml,一次只能更新一个值,而text()选择器找不到空元素,所以你首先需要清空元素,然后插入值,然后为每场比赛):

      SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/text())[1] with "40"')
      SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/text())[2] with "40"')
      
      SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/text())[1] with ""')
      SET @tXML.modify('insert text{"This Works"} into (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])[1]')
      
      SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/text())[2] with ""')
      SET @tXML.modify('insert text{"This Works"} into (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])[2]')
      

      以及插入和删除属性

      -- insert attribute
      -- SET @tXML.modify('insert attribute data-objid1 {"1"} into (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])[1]')
      -- delete attribute
      -- and then, delete suddenly can remove several nodes - unlike insert or modify ... 
      -- SET @tXML.modify('delete (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])/@data-objid[1]')
      
      -- only insert if there is no attribute "data-objid", therefore check with [not(@data-objid)]
      -- (on replace, it doesn't create an attribute if it doesn't exist)
      SET @tXML.modify('insert attribute data-objid {"1"} into (//path[not(@data-objid) and contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0])[1]')
      SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/@data-objid)[1] with "Test"')
      

      还有变量:

      DECLARE @testvar varchar(30); 
      SET @testvar = 'abc'; 
      SET @tXML.modify('insert attribute data-objid {sql:variable("@testvar")} into (//path[not(@data-objid)] and contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0)[1]')
      SET @tXML.modify('replace value of (//path[contains("0000X1,0000X2", @data-objid) and string-length(@data-objid) != 0]/@data-objid)[1] with sql:variable("@testvar")')
      SET @testvar = '0000X1,0000X2'; 
      SET @tXML.modify('delete (//path[contains(sql:variable("@testvar"), @data-objid) and string-length(@data-objid) != 0])/@data-objid[1]')
      

      请注意,您应该将属性data-objid 连接到("," + objid + ","),这样如果testvar 是',0000X1a,0000X2b,' 而不是',0000X1,0000X2,'(例如),修改就不会意外找到它

      DECLARE @testvar varchar(30); 
      SET @testvar = ',0000X1a,0000X2b,'; 
      SET @tXML.modify('delete (//path[contains(sql:variable("@testvar"), concat(",", @data-objid, ",")) and string-length(@data-objid) != 0])/@data-objid[1]')
      
      SELECT @tXML 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多