我正在将 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
内部。
我的做法:
gemeinde
的所有 references替换为原始的完整
gemeinde
对象。<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>
节点不会被引用替换。
注意事项:
<fieldToDelete>
可能不包含 <gemeinde id="1234">
,而是包含 <gemeinde reference="1234">
。如果 XML 中 <gemeinde>
节点已经出现在 fieldToDelete
之前,就会发生这种情况。 (首次出现的 gemeinde
始终具有 id
,所有其他节点仅具有 reference
。)你的问题不太清楚。也许这样的东西适合你:
<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>
只有链接两个转换(步骤),即运行两个不同的链接样式表或使用两种模式时,您的方法才有效。
我建议使用钥匙
<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"/>