在 xpath 谓词中循环此序列时按顺序检索当前节点

如何解决在 xpath 谓词中循环此序列时按顺序检索当前节点

我需要转换这个输入的xml:

<Problems>
    <problem location="engineroom/boiler/nozzle"/>
    <problem location="engineroom/boiler/nozzle/leak"/>
    <problem location="office/printer/paper"/>
    <problem location="office/printer/paper/empty/A4"/>
    <problem location="office/printer/paper/empty/A3"/>
    <problem location="garage/truck/window"/>
    <problem location="garage/truck/window/crack"/>
</Problems>

到这个输出xml:

<Problems>
    <problem ignore="leak"/>
    <problem ignore="leak"/>
    <problem ignore="empty"/>
    <problem ignore="empty"/>
    <problem ignore="empty"/>
    <problem location="garage/truck/window"/>
    <problem location="garage/truck/window/crack"/>
</Problems>

我当前的代码涉及对感兴趣的项目('leak'、'empty')及其父元素('nozzle'、'paper')进行硬编码

    <xsl:template match="@* | node()">
        <xsl:copy>
            <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
    </xsl:template>
    
    <xsl:template match="problem[contains(@location,'leak')]
        | problem[ends-with(@location,'nozzle')][contains(following-sibling::problem[1]/@location,'nozzle/leak')]">
        <xsl:apply-templates select="." mode="display">
            <xsl:with-param name="location" select="'leak'"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="problem[contains(@location,'empty')]
        | problem[ends-with(@location,'paper')][contains(following-sibling::problem[1]/@location,'paper/empty')]">
        <xsl:apply-templates select="." mode="display">
            <xsl:with-param name="location" select="'empty'"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="problem[contains(@location,'burnt')]
        | problem[ends-with(@location,'PCB')][contains(following-sibling::problem[1]/@location,'PCB/burnt')]">
        <xsl:apply-templates select="." mode="display">
            <xsl:with-param name="location" select="'burnt'"/>
        </xsl:apply-templates>
    </xsl:template>

    <xsl:template match="problem" mode="display">
        <xsl:param name="location"/>
        <problem ignore="{$location}"/>
    </xsl:template>

我尝试过的如下。但我不知道如何将序列中的当前节点(例如“泄漏”)传递给“显示”模板。另外,请让我知道是否有比这个丑陋的匹配表达式更好的方法。谢谢!

    <xsl:variable name="issues">
        <issue name="leak" parent="nozzle"/>
        <issue name="empty" parent="paper"/>
        <issue name="burnt" parent="PCB"/>
    </xsl:variable>
    
    <xsl:template match="problem[true() = (for $i in $issues/issue return if(
        contains(@location,$i/@name)
        or ends-with(@location,$i/parent) and contains(following-sibling::problem[1]/@location,$i/@name)
        ) then true() else false())]">
        <xsl:apply-templates select="." mode="display">
            <xsl:with-param name="location" select="'???'"/>
        </xsl:apply-templates>
    </xsl:template>

解决方法

我不确定我是否理解了这个问题,但所提供的算法似乎可以在 XSLT 3 中实现为

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:map="http://www.w3.org/2005/xpath-functions/map"
    exclude-result-prefixes="#all"
    version="3.0">
    
  <xsl:param name="relations" as="map(xs:string,xs:string)"
    select="map { 'leak' : 'nozzle','empty' : 'paper' }"/>
    
  <xsl:variable name="relation-keys" select="map:keys($relations)"/>

  <xsl:mode on-no-match="shallow-copy"/>
  
  <xsl:template match="problem[some $key in $relation-keys satisfies contains(@location,$key)]">
       <xsl:apply-templates select="." mode="display">
            <xsl:with-param name="location" select="$relation-keys[contains(current()/@location,.)]"/>
        </xsl:apply-templates>
  </xsl:template>
  
  <xsl:template match="problem[some $key in $relation-keys 
                               satisfies (ends-with(@location,$relations($key)) and contains(following-sibling::problem[1]/@location,$key))]">
       <xsl:apply-templates select="." mode="display">
            <xsl:with-param name="location" select="$relation-keys[ends-with(current()/@location,$relations(.)) and contains(current()/following-sibling::problem[1]/@location,.)]"/>
        </xsl:apply-templates>      
  </xsl:template>

  <xsl:template match="problem" mode="display">
    <xsl:param name="location"/>
    <problem ignore="{$location}"/>
  </xsl:template>
  
</xsl:stylesheet>
,

这个 XSLT 2.0 转换

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output omit-xml-declaration="yes" indent="yes"/>
 
 <xsl:key name="kIgnorable" match="problem" use=
   "generate-id(current())
      [$pIgnorable/p[contains(current()/@location,concat('/',@part,'/',issue))]]"/>
 
 <xsl:param name="pIgnorable">
   <p part="nozzle">
      <issue>leak</issue>
   </p>
   <p part="paper">
     <issue>empty</issue>
   </p>
   <p part="PCB">
     <issue>burnt</issue>
   </p>
 </xsl:param>

  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>
  
  <xsl:template match="problem
  [
   for $part in tokenize(@location,'/')[last()][. = $pIgnorable/p/@part],$issue in $pIgnorable/p[@part = $part]/issue
     return
       following-sibling::problem[1]
         [
          contains(@location,$part,$issue))
         ]
  ]">
    <xsl:variable name="vPart" select="tokenize(@location,'/')[last()]"/>
    <xsl:variable name="vIssue" select=
    "substring-before(concat(following-sibling::problem[1]
                              /substring-after(@location,$vPart,'/')),'/'),'/')
    "/>
    <problem ignore="{$vIssue}"/>
  </xsl:template>
  
  <xsl:template match="problem[key('kIgnorable',generate-id())]">
     <xsl:variable name="vIgnoreRule" 
       select="$pIgnorable/p[contains(current()/@location,issue))]"/>
     <problem ignore="{$vIgnoreRule/issue}"/>
  </xsl:template>
</xsl:stylesheet>

应用于提供的 XML 文档时

<Problems>
    <problem location="engineroom/boiler/nozzle"/>
    <problem location="engineroom/boiler/nozzle/leak"/>
    <problem location="office/printer/paper"/>
    <problem location="office/printer/paper/empty/A4"/>
    <problem location="office/printer/paper/empty/A3"/>
    <problem location="garage/truck/window"/>
    <problem location="garage/truck/window/crack"/>
</Problems>

产生想要的、正确的结果

<Problems>
    <problem ignore="leak"/>
    <problem ignore="leak"/>
    <problem ignore="empty"/>
    <problem ignore="empty"/>
    <problem ignore="empty"/>
    <problem location="garage/truck/window"/>
    <problem location="garage/truck/window/crack"/>
</Problems>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?