【问题标题】:XPath - extract value from parent with highest node valueXPath - 从具有最高节点值的父节点中提取值
【发布时间】:2012-01-19 15:50:36
【问题描述】:

这是我的 XML sn-p

    <FinancialSummary>
            <SummaryDate format="YYYYMMDD">20111231</SummaryDate>
            <Revenue currency="EUR">1249164523</Revenue>
    </FinancialSummary>
    <FinancialSummary>
            <SummaryDate format="YYYYMMDD">20101231</SummaryDate>
            <Revenue currency="EUR">1242344523</Revenue>
    </FinancialSummary>
    <FinancialSummary>
            <SummaryDate format="YYYYMMDD">20091231</SummaryDate>
            <Revenue currency="EUR">324900932</Revenue>
    </FinancialSummary>

我正在尝试从财务摘要标签中具有最高数字摘要日期值的收入节点中提取节点内容。

/FinancialSummary[SummaryDate = '20111231']/Revenue

此 xpath 返回正确 = 1249164523

max(/FinancialSummary/SummaryDate)

此 xpath 返回正确 = 20111231

但是,当我尝试将两者结合起来时,什么都没有返回

/FinancialSummary[SummaryDate = max(/FinancialSummary/SummaryDate)]/Revenue

我有什么遗漏吗?这个谜题的解法是什么?

额外信息:我尝试了 contains 而不是 '=' 但没有运气

【问题讨论】:

  • 在我看来这里缺少一些东西。您的第一个表达式以/ 开头,并且XML 文档只能有一个根。您的最后一个表达式也包含这个斜杠,这意味着它只能返回一个东西,即第一个也是唯一一个文档根节点的收入元素,但前提是它满足您的谓词。同样,您的中间表达式似乎也无法返回正确的数据。你确定这是整个上下文吗?
  • @Abel,我同意你的说法,但术语令人困惑。只能有一个“根”,但这指的是根节点(/),而不是最外层的元素。因此“根节点的收入元素”没有意义......根节点的唯一子节点是 FinancialSummary 元素。您显然是指最外层元素的收入元素子级。
  • @LarsH:我们同意的只有一个根。在示例 XML 中有三个“根”,这是无效的。谓词[SummaryDate = max(/FinancialSummary/SummaryDate)] 选择了一些东西,但没有什么可以选择:只有一个根,那里没有选择。我同意我的措辞模棱两可。我的意思是说 “只要根节点满足谓词,表达式就会找到作为根节点 (FinancialSummary) 子节点的所有收入元素”
  • @Abel,XML 和 XPath 规范之间关于“根”是否可以表示元素的规范存在差异,或者至少是混乱的(参见 w3.org/TR/xpath/#root-node)。为避免混淆,最好将没有元素父级的元素称为“文档元素”、“顶级元素”或“最外层元素”。其中,当 XML 片段不是格式良好的文档时,“文档元素”会出现问题。
  • 完整的 xpath 实际上更长。我没有写完整的 xpath,因为我不想显示太多的公司信息,也不想让你感到困惑,因为我刚刚从 xml 发布了一个 sn-p。不过,我似乎在“不令人困惑”的部分有点失败,当我发布它时,这似乎是个好主意。

标签: xml xpath xsd xpath-2.0


【解决方案1】:

这有效(注意 // 而不是 / 和谓词中的上下文父级的转移):

//FinancialSummary[SummaryDate=max(../FinancialSummary/SummaryDate)]/Revenue

但是,甚至更好(即更严格和更有效)提供基于您文档的实际结构的FinancialSummary 的直接路径。

示例 XML 中的问题和建议的解决方案:

  • 您提供的 XML 示例格式不正确
  • 您的表达式从根 (/) 开始,但您的实际文档可能不包含根 FinancialSummary(因为看起来这些元素在树中更靠后)

【讨论】:

  • +1 这正是我的意思(见我的评论)。这看起来更像是一个合适的解决方案。实际上,// 在大多数处理器上具有代码气味且速度较慢,应该由 OP 在他的解决方案中通过直接路径将其删除。
【解决方案2】:

我认为这个表达回答了你的问题:

FinancialSummary[SummaryDate = max(./parent::*/FinancialSummary/SummaryDate)]/Revenue

谓词中的上下文是 FinancialSummary。你必须在树上起床才能得到其他人。如果某些节点具有相同的日期,则此表达式可以返回多个节点。

编辑

我删除了第一个斜线。 后果:您必须在正确的上下文中(FinancialSummary 的父级)才能启动此 XPath 查询。

【讨论】:

  • 他的表达式以/ 开头,一直到文档的根目录。要从当前节点开始,他应该改写./。但是您的表达式仍然可以作为解决方案,因为它会搜索文档的任何第一个子项。
  • 请注意./parent::*/ 等价于../
【解决方案3】:

我想知道当两个 XPath 组合时它不起作用的原因是否是在第一种情况下,您将 SummaryDate 与一个字符串 '20111231' 进行比较,但在第二种情况下,您将 SummaryDate 与一个字符串进行比较号码,max(...)

要对此进行测试,请尝试

/FinancialSummary[SummaryDate =
     string(max(/FinancialSummary/SummaryDate))]/Revenue

另外,我同意@Able 和@lwburk 的观点,如果您不尝试将格式错误的 XML 样本(多个顶级元素)视为实际的 XML 文档(使用“/FinancialSummary/...”)。我猜你是想简明扼要,只交流你认为与问题相关的内容。但这显然是不对的,它引发了各种各样的警报。明确这一点会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 2015-03-30
    • 2023-03-16
    • 2020-06-11
    • 2012-02-19
    相关资源
    最近更新 更多