使用XSLT包装元素,但不包括最后匹配的元素



我正在尝试将旧的XML文件转换为新的改进结构。其中一部分需要我将一些松散的元素包装到父容器中,并修改它们的子

<<p> 老结构/strong>
<monograph>
  <title>asdf</title>
  <dosage.sec id="dosage.sec.1">
    <dosage.sec>asgfd</dosage.sec>
    <dosage.sec>asgfd</dosage.sec>
  </dosage.sec>
  <dosage.sec id="dosage.sec.2">
    <dosage.sec>asgfd</dosage.sec>
    <dosage.sec>asgfd</dosage.sec>
  </dosage.sec>
  <dosage.sec id="dosage.sec.3">
    <dosage.sec>asgfd</dosage.sec>
    <dosage.sec>asgfd</dosage.sec>
  </dosage.sec>
  <products>
    <prod>sadf</prod>
    <prod>sadf</prod>
  </products>
</monograph>

新结构

<monograph>
  <title>asdf</title>
  <dosage>
    <dosage.sec id="dosage.sec.1">
      <dosage.qual>asgfd</dosage.qual>
      <dosage.qual>asgfd</dosage.qual>
    </dosage.sec>
    <dosage.sec id="dosage.sec.2">
      <dosage.qual>asgfd</dosage.qual>
      <dosage.qual>asgfd</dosage.qual>
    </dosage.sec>
    <dosage.sec id="dosage.sec.3">
      <dosage.qual>asgfd</dosage.qual>
      <dosage.qual>asgfd</dosage.qual>
    </dosage.sec>
  </dosage>
  <products>
    <prod>sadf</prod>
    <prod>sadf</prod>
  </products>
</monograph>

我找到了这个答案,并根据我的需要稍微修改了一下:

<!-- wrap dosage.sec elements in a dosage container -->
<xsl:template match="node()|@*" name="dosage.sec">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*" />
    </xsl:copy>
</xsl:template>
<xsl:template match="monograph/dosage.sec[not(preceding-sibling::*[1][self::dosage.sec])]">
    <dosage>
        <xsl:call-template name="dosage.sec" />
        <xsl:apply-templates mode="copy" select="following-sibling::*[1][self::dosage.sec]" />
    </dosage>
</xsl:template>
<xsl:template match="monograph/dosage.sec" mode="copy">
    <xsl:call-template name="dosage.sec"/>
</xsl:template>

<!-- rename children dosage.sec -->
<xsl:template match="dosage.sec/dosage.sec">
    <dosage.qual>
        <xsl:apply-templates />
    </dosage.qual>
</xsl:template>

但是输出是:

<monograph>
  <title>asdf</title>
  <dosage>
    <dosage.sec id="dosage.sec.1">
      <dosage.qual>asgfd</dosage.qual>
      <dosage.qual>asgfd</dosage.qual>
    </dosage.sec>
    <dosage.sec id="dosage.sec.2">
      <dosage.qual>asgfd</dosage.qual>
      <dosage.qual>asgfd</dosage.qual>
    </dosage.sec>
    <dosage.sec id="dosage.sec.3">
      <dosage.qual>asgfd</dosage.qual>
      <dosage.qual>asgfd</dosage.qual>
    </dosage.sec>
  </dosage>
  <dosage.sec id="dosage.sec.3">
    <dosage.qual>asgfd</dosage.qual>
    <dosage.qual>asgfd</dosage.qual>
  </dosage.sec>
  <products>
    <prod>sadf</prod>
    <prod>sadf</prod>
  </products>
</monograph>

我使用PHP5的内置XSLTProcessor对象-所有XML和XSL都是1.0版本

这个怎么样:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
  <xsl:template match="@* | node()">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()"/>
    </xsl:copy>
  </xsl:template>
  <xsl:template match="monograph">
    <xsl:copy>
      <dosage>
        <xsl:apply-templates select="@* | node()" />
      </dosage>
    </xsl:copy>
  </xsl:template>
  <!-- rename children dosage.sec -->
  <xsl:template match="dosage.sec/dosage.sec">
    <dosage.qual>
      <xsl:apply-templates />
    </dosage.qual>
  </xsl:template>
</xsl:stylesheet>

当在示例输入上运行时,将产生:

<monograph>
  <dosage>
    <dosage.sec>
      <dosage.qual>asgfd</dosage.qual>
      <dosage.qual>asgfd</dosage.qual>
    </dosage.sec>
    <dosage.sec>
      <dosage.qual>asgfd</dosage.qual>
      <dosage.qual>asgfd</dosage.qual>
    </dosage.sec>
    <dosage.sec>
      <dosage.qual>asgfd</dosage.qual>
      <dosage.qual>asgfd</dosage.qual>
    </dosage.sec>
  </dosage>
</monograph>

我在路上遇到了其他一些问题——首先,我发现剂量。2个元素不在连续块中,我错误地创建了两个剂量容器。

这些模板解决了我的问题:

<!-- wrap dosage.sec elements in a dosage container -->
<xsl:template match="monograph/dosage.sec" name="dosage.sec">
    <xsl:param name="drugname" />
    <xsl:copy>
        <xsl:apply-templates>
            <xsl:with-param name="drugname" select="$drugname" />
        </xsl:apply-templates>
    </xsl:copy>
</xsl:template>
<xsl:template match="monograph/dosage.sec[not(preceding::dosage.sec)]">
    <xsl:param name="drugname" />
    <dosage>
        <xsl:call-template name="dosage.sec">
            <xsl:with-param name="drugname" select="$drugname" />
        </xsl:call-template>
        <xsl:apply-templates mode="copy" select="following::dosage.sec">
            <xsl:with-param name="drugname" select="$drugname" />
        </xsl:apply-templates>
    </dosage>
</xsl:template>
<xsl:template match="monograph/dosage.sec" mode="copy">
    <xsl:param name="drugname" />
    <xsl:call-template name="dosage.sec">
        <xsl:with-param name="drugname" select="$drugname" />
    </xsl:call-template>
</xsl:template>
<xsl:template match="monograph/dosage.sec[(preceding::dosage.sec)]" />

相关内容

  • 没有找到相关文章

最新更新