【问题标题】:How to conditionally delete node using xslt?如何使用 xslt 有条件地删除节点?
【发布时间】:2021-09-06 11:09:04
【问题描述】:

我正在尝试根据参数有条件地删除节点。

示例文件:

    <A>
        <B>
            <C>Student Node</C>
            <C>Teacher Node</C>
        </B>
    </A>

输出文件:

参数=1

    <A>      
        <B>
            <C>Student Node</C>
        </B>
    </A>

参数=0


<A>
    <B>
        <C>Teacher Node</C>
    </B>
</A>

这是我当前的 xslt 尝试:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
 <xsl:param name="preview_type"></xsl:param>
  
 <xsl:template match="node()|@*">
  <xsl:copy>
   <xsl:apply-templates select="node()|@*"/>
  </xsl:copy>
 </xsl:template>

  <xsl:choose>
    <xsl:when test="$preview_type = 0">
     <xsl:template match="/A/B/C[text()='Student Node']"/>
    </xsl:when>
    <xsl:otherwise>
     <xsl:template match="/A/B/C[text()='Teacher Node']"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:stylesheet>

目前,我收到错误:

SystemId Unknown; Line #13; Column #15; xsl:choose is not allowed in this position in the stylesheet!

任何帮助都会很棒。我想我缺少一些关于模板/Xslt 的概念。

GC_

【问题讨论】:

  • 参数看起来更像是你想选择由位置指定的元素,而不是删除它。其背后的逻辑是什么?
  • @zx485 对于条件1,我想删除标签,对于条件2,我想删除另一个标签。
  • @zx485 我正在使用空模板删除元素。空模板标签中没有副本。
  • 但是您的问题包括三种状态:0) 在 xsl:when 和 12 中的 param 示例中。
  • zx485 抱歉,我知道那会怎样。这两个状态是 0 和 1。

标签: java xslt


【解决方案1】:

使用本机 Java XSLT 支持的 XSLT-1.0 解决方案如下所示。比较复杂,因为 XSLT-1.0 不支持模板匹配规则中的参数。

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
  <xsl:param name="preview_type" />
  
  <xsl:template match="node()|@*">
    <xsl:copy>
      <xsl:apply-templates select="node()|@*"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="A/B">
    <xsl:copy>
      <xsl:choose>
        <xsl:when test="$preview_type = 0">
          <xsl:apply-templates select="C[text()!='Student Node']"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:apply-templates select="C[text()!='Teacher Node']"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:copy>
  </xsl:template>
  
</xsl:stylesheet>

【讨论】:

  • 今天早上测试,但我想这就是我要找的,谢谢。
【解决方案2】:

在 XSLT 2 或更高版本中,您可以使用例如&lt;xsl:template match="/A/B/C[.='Student Node'][$preview_type = 0]"/&gt;。我认为在 XSLT 1 中,匹配模式中的变量引用是不允许的,因此您需要将任何逻辑移动到模板中,任何 xsl:template 都必须是 xsl:stylesheet 根元素的顶级子元素。

【讨论】:

  • 我尝试将选择包装在模板中,但随后出现错误,我认为这意味着模板中没有模板。
  • 当我按照您的描述进行操作时,我得到:SystemId Unknown;第 16 行;第 144 列; xsl:template 在样式表的这个位置是不允许的!
  • 我发布了 &lt;xsl:template match="/A/B/C[.='Student Node'][$preview_type = 0]"/&gt; 这条线,说它将与 XSLT 2 及更高版本一起使用,并指出任何 xsl:template(这也意味着 sn-p)都需要是xsl:stylesheet。所以不知道你尝试了什么,但我的建议肯定不会给出你在原始问题和评论中提到的错误。
猜你喜欢
  • 2022-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多