lxml 查找最后一个可选 XML 元素

lxml finding last optional XML Element

我正在使用 LXML 来处理 XML 的现有块,我想要的是:

  1. 如果标签存在则更改元素值
  2. 如果不存在,则创建元素

(2) 的问题是:将元素插入块中的正确位置,其中大多数元素是可选的。注意:有一个定义结构的XSD。

例如,我想插入 <d>,如果存在,它将在 <c> 之后,如果存在,则在 <b> 之后,如果存在,则在 <a> 之后

<OuterElement>
    <a>value of a</a> --- Optional
    <b>value of b</b> --- Optional
    <c>value of c</c> --- Optional
    <d>value of d</d>
    <e>value of e</e> --- Optional
</OuterElement>

实现此目标的最巧妙/最简单的方法是什么?目前我正在使用 XPath 表达式循环元素 - 这感觉很老套。

一种方法是在 XSLT 中使用完整序列设置一个虚拟元素模板,然后在处理输入时,将虚拟元素推入一个模板,检查输入是否具有同名元素,如果有的话复制那个,否则从虚拟模板元素复制元素:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:exsl="http://exslt.org/common"
    exclude-result-prefixes="exsl"
    version="1.0">

  <xsl:param name="template">
    <OuterElement>
        <a></a>
        <b></b>
        <c></c>
        <d></d>
        <e></e>
    </OuterElement>
  </xsl:param>
  
  <xsl:variable name="template-elements" select="exsl:node-set($template)/OuterElement/*"/>

  <xsl:template match="OuterElement">
      <xsl:copy>
          <xsl:apply-templates select="$template-elements">
              <xsl:with-param name="input" select="."/>
          </xsl:apply-templates>
      </xsl:copy>
  </xsl:template>
  
  <xsl:template match="OuterElement/*">
      <xsl:param name="input"/>
      <xsl:choose>
          <xsl:when test="$input/*[name() = name(current())]">
              <xsl:copy-of select="$input/*[name() = name(current())]"/>
          </xsl:when>
          <xsl:otherwise>
              <xsl:copy-of select="."/>
          </xsl:otherwise>
      </xsl:choose>
  </xsl:template>
  
  <xsl:output indent="yes"/>
  
</xsl:stylesheet>

不幸的是,对于 XSLT 1,我们需要使用 exsl:node-set 函数将参数结果树片段转换为节点集。