【问题标题】:How to apply triple level of condition in an XPATH如何在 XPATH 中应用三级条件
【发布时间】:2013-03-11 17:51:47
【问题描述】:

这是我从 Zoho CRM 获得的 XML,我需要获取记录主要联系人的电子邮件:

<!--?xml version="1.0" encoding="UTF-8" ?-->
  <response uri="/crm/private/xml/Contacts/getRelatedRecords">
     <result>
       <contacts>
        <row no="1">
           <fl val="CONTACTID">511618000000889989</fl>
           <fl val="Email">
               <!--[CDATA[person1@example.com]]-->
           </fl>
           <fl val="Primary">
               <!--[CDATA[true]]-->
           </fl>
        </row>
        <row no="2">
           <fl val="CONTACTID">511617845475451213</fl>
           <fl val="Email">
              <!--[CDATA[person2@example.com]]-->
           </fl>
           <fl val="Primary">
              <!--[CDATA[false]]-->
           </fl>
        </row>
       </contacts>
     </result>
  </response>

在上述情况下,xpath 表达式应返回 person1@example.com 作为主要人员的电子邮件。

我开始将表达式写为:

/response/result/contacts/row[./fl/@val='Primary' and ]/fl[@val='Email']/text()

但无法为行元素编写组合谓词。

另一个问题是命名空间。似乎这个 XML 有一个命名空间。这种情况下如何处理 XPATH 中的命名空间?

【问题讨论】:

    标签: xml xpath expression multi-level


    【解决方案1】:

    您的 CDATA 部分不应写为注释。 假设你替换

    <!--[CDATA[true]]-->
    

    <![CDATA[true]]>
    

    您可以通过以下方式获取您的地址

    //row[fl[@val="Primary" and matches(text(),"true")]]/fl[@val="Email"]/text()
    

    如果您现在无法控制 CDATA 的生成,并且想将它们视为注释,请选择

    //row[fl[@val="Primary" and matches(comment(),"true")]]/fl[@val="Email"]/substring-before(substring-after(comment(),"CDATA["),"]]")
    

    【讨论】:

    • 谢谢。但由于某种原因,它无法解析 match 函数。是需要给某个系统命名空间还是某个函数执行与某个级别的实现解析器实现有关?
    • 如果它不能识别matches(),这意味着你使用的是XPath 1.0。在这种情况下,将 match() 替换为 contains()。但是您将无法在定位步骤中使用任何功能,您必须在第二步中提取您的电子邮件值。
    • 您能否详细说明您所说的两个步骤是什么意思?任何指针将不胜感激。
    • 我的意思是 xpath 表达式将返回 CDATA 字段,括在括号中,例如 [CDATA[person2@example.com]]。您需要使用调用 xpath 表达式的代码来提取电子邮件地址。
    • 太棒了!它就像@A Hocevar 的魅力。谢谢你的帮助。这在 .Net 中有效,但 Zoho Parser 仍然存在问题。我认为XPATH是正确的,似乎是ZOHO使用的解析器有问题。
    【解决方案2】:

    这行得通吗?

    //fl[@val='Primary' and contains(text(), 'true')]//preceding-sibling::fl[@val='Email']
    

    【讨论】:

    • 遗憾的是,真正的 XML 并没有这两个节点相邻。感谢您的输入。欣赏它。
    【解决方案3】:

    假设那些 CDATA 部分实际上 CDATA 部分而不是 cmets,应该这样做:

    /response/result/contacts/row[normalize-space(fl[@val = 'Primary]) = 'true']
                                 /fl[@val = 'Email']
    

    据我所知,您的 XML 不使用命名空间。 uri= 只是一个普通的属性。

    【讨论】:

    • 无法控制 XML 生成,因为它来自外部系统。不过感谢四点意见。
    猜你喜欢
    • 2012-10-18
    • 2018-05-17
    • 1970-01-01
    • 2022-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-14
    相关资源
    最近更新 更多