繁体   English   中英

使用 XSLT 用 ABC 替换特定的 XML 节点值

[英]Replace Specific XML Node value with ABC using XSLT

示例 XML:

<MAIN>
    <A>
        <first_name>Franklin</first_name>
        <first_name_Previous></first_name_Previous>
        <formal_name>Franklin Alagala </formal_name>
        <gender>M</gender>
        <is_overridden>false</is_overridden>
    </A>
    <B>
        <first_name>Franklin</first_name>
        <formal_name>Franklin Alagala </formal_name>
        <gender>M</gender>
        <gender_Previous></gender_Previous>
        <is_overridden>false</is_overridden>
    </B>
</MAIN>

预期输出:

<MAIN>
    <A>
        <first_name>Franklin</first_name>
        <first_name_Previous>ABCD</first_name_Previous>
        <formal_name>Franklin Alagala </formal_name>
        <gender>M</gender>
        <is_overridden>false</is_overridden>
    </A>
    <B>
        <first_name>Franklin</first_name>
        <formal_name>Franklin Alagala </formal_name>
        <gender>M</gender>
        <gender_Previous>ABCD</gender_Previous>
        <is_overridden>false</is_overridden>
    </B>
</MAIN>

想要替换包含名称的节点,并且该节点为空。 但是,如果节点包含 name as previous 并且 value 存在,则应保留 name 原样。

让我把你的描述换一种方式,这更好地导致预期的解决方案。

  1. 您查看MAIN每个子元素( AB以及可能的CD等),我们称之为buckets

  2. 您要按以下方式处理每个存储桶:

    • 查看它的每个子元素。
    • 如果此元素没有空文本内容,则保持不变。
    • 否则(此元素没有文本)读取同名在前一个存储桶中的元素的内容。
    • 如果刚刚读取的值不为空,则将当前元素的文本设置为该值。
    • 否则将当前元素的内容设置为ABCD

那么我们就可以将上面的规则用XSL写成如下:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
  <xsl:output method="xml" indent="yes" />

  <xsl:template match="MAIN/*/*">
    <xsl:copy>
      <xsl:call-template name="proc_node"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template name="proc_node">
    <xsl:variable name="thisName" select="name()"/>
    <xsl:variable name="cnt" select="string-length(.)"/>
    <xsl:if test="$cnt &gt; 0">
      <xsl:value-of select="."/>
    </xsl:if>
    <xsl:if test="$cnt = 0">
      <xsl:variable name="prevBucket" select="../preceding-sibling::*[1]"/>
      <xsl:variable name="prevElem" select="$prevBucket/*[name()=$thisName]"/>
      <xsl:variable name="cnt" select="string-length($prevElem)"/>
      <xsl:if test="$cnt &gt; 0">
        <xsl:value-of select="$prevElem"/>
      </xsl:if>
      <xsl:if test="$cnt = 0">ABCD</xsl:if>
    </xsl:if>
  </xsl:template>

  <xsl:template match="@*|node()">
    <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
  </xsl:template>
</xsl:transform>

我不知道如何找到名称中带有前一个的节点。

尝试:

*[contains(name(), 'Previous')]

如果您想进一步将其限制为空元素,您可以使用:

*[contains(name(), 'Previous') and not(node())]

请注意,XML 区分大小写; “上一个”与“上一个”不一样。

我已经编写了运行良好的代码:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:date="http://exslt.org/dates-and-times" extension-element-prefixes="date">
    <xsl:output indent="yes" />
    <xsl:template match="@*|node()">
        <xsl:copy>
        <xsl:if test="contains(name(), '_previous')">
         <xsl:if test="not(string(.))">PREVIOUS</xsl:if>      
        </xsl:if>
            <xsl:apply-templates select="@*|node()"/>
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM