xslt 转换以删除重复对象

问题描述 投票:0回答:2

我正在将 java 对象序列化为 XML,稍后需要通过 xslt 转换该 xml。

在这个特定的转换中,我需要删除一个名为

fieldToDelete
的节点(=Java 字段),它可能包含一堆不相关的信息。但是,它也可以包含名为
gemeinde
:

的节点
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <fieldToDelete>
        <gemeinde id="1234">
            <child></child>
        </gemeinde>
    </fieldToDelete>
    <gemeinde reference="1234">
    <gemeinde reference="1234">
</root>

我用

删除这些节点
<xsl:template match="fieldToDelete"/>

但是,因为这也会删除

<gemeinde>
,所以我需要恢复引用。

结果应该如下所示:

<root>        
    <gemeinde id="1234">
        <child></child>
    </gemeinde>
    <gemeinde reference="1234">
</root>

fieldToDelete
消失了,第一个
<gemeinde reference="1234">
被替换为完整的对象,该对象最初位于
fieldToDelete
内部。

我的做法:

  1. 复制:将 gemeinde 的所有
    references
    替换为原始的完整
    gemeinde
    对象。
  2. 删除不需要的字段
  3. 去重复:将除第一次出现的
    <gemeinde>
    之外的所有内容替换为引用。

这是我的xslt:

<!-- For all <gemeinde reference="<id>">, copy the referenced object instead -->
<xsl:template match="gemeinde[@reference]">
    <xsl:variable name="refId" select="@reference"/>
    <xsl:copy-of select="//gemeinde[@id = $refId]"/>
</xsl:template>

<!-- Delete obsolete field (which contains <gemeinde> sub-element) -->
<xsl:template match="fieldToDelete"/>

<!-- We might now have duplicate <gemeinde> definitions, replace all but the first one with a reference instead -->
<xsl:template match="gemeinde[@id]">
    <xsl:variable name="refId" select="@id"/>

    <xsl:if test="preceding::gemeinde[@id=$refId]">
        <xsl:copy>
            <!-- Rename 'id' attribute to 'reference' -->
            <xsl:attribute name="reference">
                <xsl:value-of select="@id"/>
            </xsl:attribute>
        </xsl:copy>
    </xsl:if>
</xsl:template>

但是,这段代码(特别是“

preceding
”子句)似乎无法正常工作。 完整的
<gemeinde>
节点不会被引用替换。

注意事项:

  • ID/参考很重要。可以有多个具有不同ID的gemeinde对象,并且它们不能混淆。
  • <fieldToDelete>
    可能不包含
    <gemeinde id="1234">
    ,而是包含
    <gemeinde reference="1234">
    。如果 XML 中
    <gemeinde>
    节点已经出现在
    fieldToDelete
    之前,就会发生这种情况。 (首次出现的
    gemeinde
    始终具有
    id
    ,所有其他节点仅具有
    reference
    。)
java xml xslt
2个回答
0
投票

你的问题不太清楚。也许这样的东西适合你:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>

<xsl:key name="gi" match="gemeinde" use="@reference" />

<xsl:template match="/root">
    <xsl:copy>
        <xsl:copy-of select="fieldToDelete/gemeinde"/>
        <xsl:copy-of select="gemeinde[generate-id() = generate-id(key('gi', @reference)[1])]"/>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>

0
投票

只有链接两个转换(步骤),即运行两个不同的链接样式表或使用两种模式时,您的方法才有效。

我建议使用钥匙

  <xsl:key name="gemeinde-by-id" match="gemeinde" use="@id"/>
  <xsl:key name="gemeinde-by-ref" match="gemeinde" use="@reference"/>
  
  <xsl:template match="fieldToDelete"/>
  
  <xsl:template match="gemeinde[@reference][. is key('gemeinde-by-ref', @reference)[1]]">
    <xsl:sequence select="key('gemeinde-by-id', @reference)"/>
  </xsl:template>

  <xsl:mode on-no-match="shallow-copy"/>
© www.soinside.com 2019 - 2024. All rights reserved.