查找 XML 节点集的最低公共祖先

2024-01-17

我有一个使用 XSLT 中的 xsl:key 结构构造的节点集。我想找到该节点集中所有节点的最低共同祖先(LCA) - 有什么想法吗?

我了解 Kaysian intersects 和 XPath 的 intersect 函数,但这些似乎是为了找到一对元素的 LCA:我事先不知道每个节点集中有多少项。

我想知道是否有一种解决方案可以使用“every”和“intersect”表达式的组合,但我还没有想到!

提前致谢, 汤姆


这是一种自下而上的方法:

 <xsl:function name="my:lca" as="node()?">
  <xsl:param name="pSet" as="node()*"/>

  <xsl:sequence select=
   "if(not($pSet))
      then ()
      else
       if(not($pSet[2]))
         then $pSet[1]
         else
           if($pSet intersect $pSet/ancestor::node())
             then
               my:lca($pSet[not($pSet intersect ancestor::node())])
             else
               my:lca($pSet/..)
   "/>
 </xsl:function>

A test:

<xsl:stylesheet version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:my="my:my">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>

    <xsl:variable name="vSet1" select=
      "//*[self::A.1.1 or self::A.2.1]"/>

    <xsl:variable name="vSet2" select=
      "//*[self::B.2.2.1 or self::B.1]"/>

    <xsl:variable name="vSet3" select=
      "$vSet1 | //B.2.2.2"/>

 <xsl:template match="/">
<!---->
     <xsl:sequence select="my:lca($vSet1)/name()"/>
     =========

     <xsl:sequence select="my:lca($vSet2)/name()"/>
     =========

     <xsl:sequence select="my:lca($vSet3)/name()"/>

 </xsl:template>

 <xsl:function name="my:lca" as="node()?">
  <xsl:param name="pSet" as="node()*"/>

  <xsl:sequence select=
   "if(not($pSet))
      then ()
      else
       if(not($pSet[2]))
         then $pSet[1]
         else
           if($pSet intersect $pSet/ancestor::node())
             then
               my:lca($pSet[not($pSet intersect ancestor::node())])
             else
               my:lca($pSet/..)
   "/>
 </xsl:function>
</xsl:stylesheet>

当此转换应用于以下 XML 文档时:

<t>
    <A>
        <A.1>
            <A.1.1/>
            <A.1.2/>
        </A.1>
        <A.2>
            <A.2.1/>
        </A.2>
        <A.3/>
    </A>
    <B>
        <B.1/>
        <B.2>
            <B.2.1/>
            <B.2.2>
                <B.2.2.1/>
                <B.2.2.2/>
            </B.2.2>
        </B.2>
    </B>
</t>

所有三种情况都会产生所需的正确结果:

     A
     =========

     B
     =========

     t

Update:我有我认为可能是最有效的算法。

这个想法是,节点集的 LCA 与该节点集的两个节点的 LCA 相同:“最左边”和“最右边”节点。证明这是正确的证明留给读者作为练习:)

这是完整的 XSLT 2.0 实现:

<xsl:stylesheet version="2.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:my="my:my">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>

        <xsl:variable name="vSet1" select=
          "//*[self::A.1.1 or self::A.2.1]"/>

        <xsl:variable name="vSet2" select=
          "//*[self::B.2.2.1 or self::B.1]"/>

        <xsl:variable name="vSet3" select=
          "$vSet1 | //B.2.2.2"/>

     <xsl:template match="/">
         <xsl:sequence select="my:lca($vSet1)/name()"/>
         =========

         <xsl:sequence select="my:lca($vSet2)/name()"/>
         =========

         <xsl:sequence select="my:lca($vSet3)/name()"/>

     </xsl:template>

     <xsl:function name="my:lca" as="node()?">
      <xsl:param name="pSet" as="node()*"/>

      <xsl:sequence select=
       "if(not($pSet))
          then ()
          else
           if(not($pSet[2]))
             then $pSet[1]
             else
              for $n1 in $pSet[1],
                  $n2 in $pSet[last()]
               return my:lca2nodes($n1, $n2)
       "/>
     </xsl:function>

     <xsl:function name="my:lca2nodes" as="node()?">
      <xsl:param name="pN1" as="node()"/>
      <xsl:param name="pN2" as="node()"/>

      <xsl:variable name="n1" select=
       "($pN1 | $pN2)
                    [count(ancestor-or-self::node())
                    eq
                     min(($pN1 | $pN2)/count(ancestor-or-self::node()))
                    ]
                     [1]"/>

      <xsl:variable name="n2" select="($pN1 | $pN2) except $n1"/>

      <xsl:sequence select=
       "$n1/ancestor-or-self::node()
                 [exists(. intersect $n2/ancestor-or-self::node())]
                     [1]"/>
     </xsl:function>
</xsl:stylesheet>

当对同一个 XML 文档(上面)执行此转换时,会产生相同的正确结果,但速度要快得多 — 特别是在节点集的大小很大的情况下:

 A
 =========

 B
 =========

 t
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

查找 XML 节点集的最低公共祖先 的相关文章

  • 基于已知 XSL 对未知 XML 进行逆向工程

    Solved 在遵循 Matti 的建议后 我删除了自定义函数 一切都很好 原帖 截至今天 我还是 XSLT 的新手 所以我确信这对你们中的许多人来说是理所当然的 无论如何 我的任务是使用第三方供应商提供的数据为我公司的网站创建一个小部件
  • 使用 TinyXml2 提取子树 XML 字符串

    我想做和里面那个人完全相同的事情这个问题 https stackoverflow com questions 11935689 how to convert an xmlelement to string in tinyxml2 我想将 X
  • 使用 XSLT(即 XML Transformer)时防止 DTD 下载

    我必须在 Java 中处理具有 DTD 和 XSLT 的 XML 文件 DTD 确实是必要的 因为它包含我使用的实体的定义 旁白 是的 将实体用于可以使用 unicode 的东西是一个坏主意 当我运行转换时 它每次都会从外部源下载 DTD
  • XSL:让原始 HTML 通过

    我正在进行 XSL 转换 我正在转换的 XML 有一个包含 html 的节点
  • C#.net 中的 XML 数据库

    我正在为一些网站开发WPF客户端程序 它使用 XML 数据库 我是 XML 新手 请有人解释一下如何创建 附加 最重要 编辑 读取和加密 XML 文件 我知道这是一个大问题 但是 事情很紧急 必须尽快完成工作 在网上查了一下 没有得到正确的
  • 如何让 XSLT 在 Java 中返回 UTF-8

    我正在尝试让我的 XSL 脚本使用 UTF 8 编码 像 和希腊字符这样的字符就像垃圾一样出现 让它工作的唯一方法是将结果写入文件 如果我将它写入输出流 它只会返回垃圾 System out 有效 但这可能是因为它被重定向到文件 结果需要从
  • Java中对象的序列化需要什么? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 谁能告诉我Java中对象序列化的需求是什么 并给我一个示例场景来解释需求 我已经了解什么是序列化 我只是想了解何时使用它以及如何使用它
  • 修改“NodeJS”上的 XML 标签

    有谁知道如何使用 NodeJS 修改 XML 文件的标签值 这是我的 XML 文件
  • XSL。评估表达

    对不起我的英语不好 XSL 1 0 如何从元素或属性值计算表达式 例如 XML
  • 如何使用 PHP 跳过 XML 文件中的无效字符

    我正在尝试使用 PHP 解析 XML 文件 但收到错误消息 解析器错误 字符 0x0 超出允许范围 我认为这是因为 XML 的内容 我认为有一个特殊符号 我能做些什么来修复它 我还得到 解析器错误 标签项行中数据过早结束 可能是什么原因导致
  • 反规范化 XSD

    我需要对 XML 模式进行非规范化 以便为将创建符合该模式的文档的人员生成文档 用户不了解 XSD 并且很可能永远不会学习 我见过的工具能够为其他 XSD 开发人员生成文档 但我的用户对如何构建架构的细节不感兴趣 他们只想知道他们可以做什么
  • 就地修改 XML 文件?

    假设我有以下 XML 文件
  • Firefox 不再解释 XSLT-1.0

    我使用 XSLT 将大量数据保存在 XML 文件中 以便在 Firefox 中正确显示内容 但从今天开始 Firefox 不再解释 XSLT 并显示白色页面或块中的数据 我当前的 Firefox 版本是 68 0 64 位 新版本中的 XS
  • XPath 获取没有父节点的所有子节点(元素、注释和文本)

    我需要一个 XPath 来获取所有没有父元素的子节点 包括文本元素 注释元素和子元素 任何帮助 示例示例
  • Xpath 和通配符

    我尝试了几种组合但没有成功 该数据的完整 xpath 是 id detail row seek 37878 td问题是每个节点的数字部分 37878 都会发生变化 因此我无法使用 foreach 循环遍历节点 有没有办法使用通配符并将 xp
  • 有没有办法将 JSON 模式转换为 XSD? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我目前正在寻找一种将 JSON 架构转换为 XSD 或 XML 架构的方法 我没有找到任何关于这个主题
  • 在Python中解析Google Earth KML文件(lxml,命名空间)

    我正在尝试解析 kml https developers google com kml documentation 使用 xml 模块将文件导入到 Python 中 在 BeautifulSoup 中未能实现此功能 我将其用于 HTML 由
  • XMLReader - 如何处理未声明的命名空间

    Merged https meta stackexchange com questions 158066 what is a merged question with 如何使用 XMLReader 读取未定义命名空间的 XML 文件 que
  • Android 中的 XmlPullParser 陷入困境

    经过多个小时的搜索和调试后 我仍然停留在同一个地方 并且 Eclipse 没有帮助我 我试图解析这个 RSS 提要 http fr espnf1 com rss motorsport story feeds 0 xml type 2 这很简
  • 不明确的 XML 模式

    我正在尝试为 XML 生成一个非常简单的 XML 架构 类似于以下内容

随机推荐

  • 如何使用 Jquery 编写“如果未单击”或“如果在元素外部单击”?

    我有点陷入如何阻止菜单执行 fadeOut 函数的问题 当我单击菜单上的主链接打开子菜单时 它就会淡出 目前代码如下 a main menu item click function if rtmenu visible rtmenu clic
  • 从字节数组创建 8 位图像

    字节数组是这样获得的 BufferedImage image new Robot createScreenCapture new Rectangle screenDimension byte array DataBufferByte get
  • 目录最后修改日期

    我想知道目录上次修改日期何时更改 我修改了特定目录中的文件 通过 FTP 但该目录的 LMD 没有更改 它应该如何运作 当添加 删除或重命名文件或子目录时 目录本身的 mtime 修改时间 会发生变化 修改目录中文件的内容不会更改目录本身
  • iphone:从相机捕获的图像改变方向

    我制作了一个 iPhone 应用程序来从相机捕获图像并在下一个视图中设置该图像 但问题是图像被旋转了 即风景图像变成肖像 肖像图像变成风景 我参考了很多代码但无法得到解决方案 我的代码是 void btnCapturePressed if
  • rust 中的类型 `` 没有实现什么特征 `core::kinds::Sized` ?

    我预计这会起作用 trait Task
  • Java EE 7 CDI - 注入不起作用,发送 NullPointerException

    我的注射有问题 这是我第一次尝试 我正在使用 Wildfly 和 Java EE 7 我有一个NullPointerException当尝试访问时Authenticator实例在LoginController 我使用maven 我的bean
  • 迄今为止的 MySQL 字符串,具有包含时区说明符的给定格式

    我的数据库中有一个字符串列 Wed Aug 13 17 51 06 GMT 05 30 2014 我可以将其转换为日期并在 where 子句中使用它来获取记录吗 where Timecolumn gt CURDATE 7 请注意 时区说明符
  • 使用 NSBorderlessWindowMask 时出现灰色边框

    每当我尝试使用 NSBorderlessWindowMask 创建自定义窗口并将 NSView 例如 NSImageView 设置为其 contentView 时 我都会在 NSView 周围出现 1px 灰色边框 并且似乎无法摆脱它 我遵
  • 将多个文件中的空格转换为制表符 Sublime Text 2

    有没有办法将所有空格转换为制表符 而不是逐个文件转换 如果我打开一个文件并浏览View gt Indentation gt Convert Indentation to Tabs 它仅更改此文件 我想将整个项目中的缩进转换为制表符 Use
  • 如何在 django 中提供创建的临时文件

    我有一个远程存储项目 当用户请求他的文件时 django 服务器会在本地检索该文件 用于某些处理 并将其存储为临时文件 然后使用 mod x sendfile 将其提供给用户 我当然希望临时文件在提供给用户后被删除 文件指出NamedTem
  • Flutter,如何删除对话框周围的空白?

    我在从服务器获取数据时调用此对话框 该对话框周围有空格 我可以删除对话框周围的空白区域吗 这是我的代码 var bodyProgress new Container decoration new BoxDecoration color Co
  • 使

    我在 SO 上看到过类似的主题 但我的略有不同 我试图让我的父级 DIV 和子级 保持焦点 直到我将注意力从 div 上移开 但这似乎很难完成 This solution https stackoverflow com a 3089045
  • 使用 Cocoa 的 Accessibility API 获取应用程序的 Dock 图标的位置

    如何使用 Accessibility API 获取应用程序的 Dock 图标的位置 找到了 使用这个论坛帖子 http cocoadev com forums discussion 1431 getting dock icon positi
  • Elasticsearch.Net 和超时

    我有一个 4 节点的 Elasticsearch 集群 我有一个 net 控制台应用程序 旨在用来自 sql 的数据填充集群 只要我将添加 或删除 记录的速度保持在相当低的水平 一切都会正常 如果我最终增加线程数 我将从控制台应用程序中看到
  • 无法在 AngularJS 中从控制器设置日期选择器日期

    我正在尝试按按钮创建一个 AngularJS 日期选择器 我在用this http angular ui github io bootstrap datepickerbootstrap ui 控件 该控件可以工作 单击按钮就会弹出 我可以选
  • 通过 Go (go 1.18) 泛型创建类型化值的新对象

    我正在 go 1 18 的 beta 版本中使用泛型 下面示例中的创建函数应该创建新的实例 T 所以 Apple 我尝试使用反射包来实现这一点 但没有运气 你能告诉我如何更改功能吗Create从下面的示例中 它创建了实例T而不是返回 nil
  • 将所有代码从 master 转移到新分支并从 master 中删除代码

    我的代码位于项目的主分支中 我希望代码位于单独的分支中 而不是在主分支中 我可以创建一个新的分支master 但是在创建分支之后 是否可以从主分支中删除所有代码 这样如果我稍后重新调整或将我的新分支合并到主分支中 就不会导致任何问题 谢谢
  • NodeJS javascript 中的异步响应循环

    我有一个使用 Express 4 的 NodeJS API 我使用 Sequelize 连接到数据库 并多次调用一个查询 我想将结果累积到一个数组中 问题是res send不等待循环结束来发送答案 my code router post p
  • 具有 SSE4.1 内在函数的双线性滤波器

    我现在正在尝试找出一种一次仅针对一个过滤样本的相当快速的双线性过滤函数 作为习惯使用内在函数的练习 最高可达 SSE41 就可以了 到目前为止我有以下内容 inline m128i DivideBy255 8xUint16 const m1
  • 查找 XML 节点集的最低公共祖先

    我有一个使用 XSLT 中的 xsl key 结构构造的节点集 我想找到该节点集中所有节点的最低共同祖先 LCA 有什么想法吗 我了解 Kaysian intersects 和 XPath 的 intersect 函数 但这些似乎是为了找到