Java 使用XSLT将特定XML节点值替换为ABC

Java 使用XSLT将特定XML节点值替换为ABC,java,xml,xslt,groovy,Java,Xml,Xslt,Groovy,示例XML: <MAIN> <A> <first_name>Franklin</first_name> <first_name_Previous></first_name_Previous> <formal_name>Franklin Alagala </formal_name> <gender>M</gende

示例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>

富兰克林
富兰克林·阿拉加拉
M
假的
富兰克林
富兰克林·阿拉加拉
M
假的
预期产出:

<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>

富兰克林
ABCD
富兰克林·阿拉加拉
M
假的
富兰克林
富兰克林·阿拉加拉
M
ABCD
假的

要替换名称为“上一个”且节点为空的节点。但是,如果节点包含名称为“上一个”且值为“存在”,则应保持名称不变。

让我将您的描述换一种方式,哪种方式更好 以达到预期的解决方案

  • 看看
    MAIN
    A
    B
    ,可能还有
    C
    D
    等等)的每个子元素,我们称之为bucket

  • 您要处理的每个bucket的处理方式如下:

    • 查看每个元素及其子元素
    • 如果此元素没有空文本内容,请保持不变
    • 否则(此元素没有文本)读取元素的内容 与同名,但在之前的存储桶中
    • 如果刚刚读取的值不是空的,则将当前元素的文本设置为该值
    • 否则,将当前元素的内容设置为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>
    
    
    ABCD
    
    我不知道如何定位名称中包含previous的节点

    尝试:

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

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

    注意XML是区分大小写的;“previous”与“previous”不同。我已经编写了运行良好的代码:

    <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>
    
    
    以前的
    
    您到底在哪里遇到了这个问题?欢迎来到Stack Overflow。这是一个在问题上寻求帮助的地方,所以如果你尝试了很多事情却遇到了困难,你可以得到帮助。这不是一个问“我该怎么做”的地方。你需要尽最大努力去做。您可以阅读更多信息,我可以阅读xslt中的xml,但是我不知道如何定位名称中包含previous的节点。我还需要XSLT1.0中的解决方案
    <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>