查找xml之间的差异差异并在Xquery中列出差异

时间:2020-11-03 05:54:18

标签: xml xpath xquery marklogic

我正在尝试按照以下步骤查找两个xml之间的区别。

  1. 获取left和内部子元素的所有不同路径 正确的xml。
  2. 绕过左侧路径,检查是否与任何路径匹配 正确的路径。
  3. 如果不匹配,则为新元素。
  4. 如果匹配,我正在做子元素map1-map2。这给了我 更改了子元素(元素和属性均更改)。

但是我需要确定发生了什么变化,无论是元素文本还是属性值并列出。

请让我知道Xquery中执行此操作的方法。

2 个答案:

答案 0 :(得分:3)

比较XML并不完全是琐碎的事,但是已经经常尝试了。不是最新的,但是您可以看一下:

https://github.com/ryanjdew/marklogic-xml-diff

我过去也使用过此方法,虽然使用XSLT而不是XQuery,但并不那么详细。不过,它对于回归测试非常有效,也可以在MarkLogic中使用:

http://xsltunit.org/xsltunit.xsl

还有一些商业产品,例如:

https://www.deltaxml.com/

不过,不确定是否也可以无头使用上述内容。

HTH!

答案 1 :(得分:0)

正如grtjn指出的那样,比较XML可能会变得非常复杂,特别是如果您的XML包含混合内容,或者如果您关心元素顺序,或者您的元素可能出现多次。如果这些都不适用,则可以采取一些捷径。

在您的示例中,将属性添加到路径列表,然后仅根据其字符串内容比较所有内容(元素和属性)可能就足够了。

路径列表必须包含属性。您可以像这样采用不同轴的并集,也可以采用必须包含属性和叶元素并排除文本节点和非叶元素的任何条件。

local:path-to-node($left/child::*/child::*/(self::*[text()]|attribute::*))

您的path-to-node函数必须能够处理被传递的属性。因此,您必须对path-to-node函数进行一些更改,以确保正确命名属性(使用“ @”),并且(如果适用)没有位置标记

declare function local:path-to-node($node as node()){
  let $attr := typeswitch ($node) case attribute() return '@' default return ()
  return string-join(('', $node/ancestor::*/name(.), $attr||name($node)), '/')
};

根据您的path-to-node函数的复杂程度,拥有两个函数可能会更容易。

fn:distinct-values((
  local:path-to-element-node($left/child::*/child::*),
  local:path-to-attribute-node($left/child::*/child::*/@*)
))
相关问题