使用XSLT和PerlXML::LibXSLT删除重复的XML元素
我有一个XML文件:使用XSLT和PerlXML::LibXSLT删除重复的XML元素,xml,perl,xslt,Xml,Perl,Xslt,我有一个XML文件: 这是输入的内容。 这是输入的内容。 我正在尝试使用删除重复的: <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" exclude-result-prefixes="d"> <xsl:output omit-xml-dec
这是输入的内容。
这是输入的内容。
我正在尝试使用删除重复的:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" exclude-result-prefixes="d">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kIndexByValueTitle" match="d:index"
use="concat(generate-id(..), '+', @d:value, '+', @d:title)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"d:index[not(generate-id()
= generate-id(key('kIndexByValueTitle',
concat(generate-id(..), '+', @d:value, '+', @d:title)
)
[1]))]" />
</xsl:stylesheet>
<d:dictionary xmlns="http://www.w3.org/1999/xhtml"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="c" d:title="c"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
<d:dictionary xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" xmlns="http://www.w3.org/1999/xhtml">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="c" d:title="c"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
对提供的XML文档应用此转换时:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" exclude-result-prefixes="d">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kIndexByValueTitle" match="d:index"
use="concat(generate-id(..), '+', @d:value, '+', @d:title)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"d:index[not(generate-id()
= generate-id(key('kIndexByValueTitle',
concat(generate-id(..), '+', @d:value, '+', @d:title)
)
[1]))]" />
</xsl:stylesheet>
<d:dictionary xmlns="http://www.w3.org/1999/xhtml"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="c" d:title="c"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
<d:dictionary xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" xmlns="http://www.w3.org/1999/xhtml">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="c" d:title="c"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
这是输入的内容。
这是输入的内容。
生成所需的正确结果:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" exclude-result-prefixes="d">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kIndexByValueTitle" match="d:index"
use="concat(generate-id(..), '+', @d:value, '+', @d:title)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"d:index[not(generate-id()
= generate-id(key('kIndexByValueTitle',
concat(generate-id(..), '+', @d:value, '+', @d:title)
)
[1]))]" />
</xsl:stylesheet>
<d:dictionary xmlns="http://www.w3.org/1999/xhtml"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="c" d:title="c"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
<d:dictionary xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" xmlns="http://www.w3.org/1999/xhtml">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="c" d:title="c"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
这是输入的内容。
这是输入的内容。
使用:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" exclude-result-prefixes="d">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kIndexByValueTitle" match="d:index"
use="concat(generate-id(..), '+', @d:value, '+', @d:title)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"d:index[not(generate-id()
= generate-id(key('kIndexByValueTitle',
concat(generate-id(..), '+', @d:value, '+', @d:title)
)
[1]))]" />
</xsl:stylesheet>
<d:dictionary xmlns="http://www.w3.org/1999/xhtml"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="c" d:title="c"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
<d:dictionary xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" xmlns="http://www.w3.org/1999/xhtml">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="c" d:title="c"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
对提供的XML文档应用此转换时:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" exclude-result-prefixes="d">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kIndexByValueTitle" match="d:index"
use="concat(generate-id(..), '+', @d:value, '+', @d:title)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"d:index[not(generate-id()
= generate-id(key('kIndexByValueTitle',
concat(generate-id(..), '+', @d:value, '+', @d:title)
)
[1]))]" />
</xsl:stylesheet>
<d:dictionary xmlns="http://www.w3.org/1999/xhtml"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="c" d:title="c"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
<d:dictionary xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" xmlns="http://www.w3.org/1999/xhtml">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="c" d:title="c"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
这是输入的内容。
这是输入的内容。
生成所需的正确结果:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" exclude-result-prefixes="d">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kIndexByValueTitle" match="d:index"
use="concat(generate-id(..), '+', @d:value, '+', @d:title)"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match=
"d:index[not(generate-id()
= generate-id(key('kIndexByValueTitle',
concat(generate-id(..), '+', @d:value, '+', @d:title)
)
[1]))]" />
</xsl:stylesheet>
<d:dictionary xmlns="http://www.w3.org/1999/xhtml"
xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="c" d:title="c"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
<d:dictionary xmlns:d="http://www.apple.com/DTDs/DictionaryService-1.0.rng" xmlns="http://www.w3.org/1999/xhtml">
<d:entry id="a" d:title="a">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<d:index d:value="c" d:title="c"/>
<div>This is the content for entry.</div>
</d:entry>
<d:entry id="b" d:title="b">
<d:index d:value="a" d:title="a"/>
<d:index d:value="b" d:title="b"/>
<div>This is the content for entry.</div>
</d:entry>
</d:dictionary>
这是输入的内容。
这是输入的内容。
有时直接使用编程库可能更容易。
使用XML::DT跟踪Perl脚本
#!/usr/bin/perl
use XML::DT;
my $filename = shift;
my %seen=();
my %handler=(
'd:entry' => sub{ %seen=(); toxml }, ## reset seen
'd:index' => sub{ if ($seen{$v{"d:value"}}++){"" } ## $v{id} -- attribute id
else {toxml}},
);
print dt($filename, %handler);
与往常一样,如果未安装,sudocpanxml::DT
。有时直接使用编程库可能更容易。
使用XML::DT跟踪Perl脚本
#!/usr/bin/perl
use XML::DT;
my $filename = shift;
my %seen=();
my %handler=(
'd:entry' => sub{ %seen=(); toxml }, ## reset seen
'd:index' => sub{ if ($seen{$v{"d:value"}}++){"" } ## $v{id} -- attribute id
else {toxml}},
);
print dt($filename, %handler);
通常,如果未安装,sudo cpan XML::DT
。xsl:for each group
需要XSLT 2.0。LibXSLT是XSLT1.0处理器。使用or.P.S。模板必须具有匹配
或名称
属性(或两者兼有)。刚刚尝试为XSLT
2.0支持安装XML::Saxon::XSLT2
,但失败了…为什么Perl
库安装起来如此困难…:(这要归咎于你不太出色的OS X软件包管理器。在Linux上用XML::Saxon::XSLT2安装dist只花了我不到一分钟的时间。xsl:for each group
需要XSLT 2.0。LibXSLT是XSLT 1.0处理器。使用或.P.S。模板必须具有匹配
或名称
属性(或两者兼有)。刚刚尝试为XSLT
2.0支持安装XML::Saxon::XSLT2
,但失败了…为什么Perl
库安装起来如此困难…:(怪你的OS X软件包管理器不够出色。在Linux上用XML::Saxon::XSLT2安装dist花了我不到一分钟的时间。谢谢你的回答。@Dimitre Novatchev我应该提到每个条目都有自己独立的@jonah_w,谢谢——你必须在问题中提供想要的结果。我编辑了答案并将其删除。)现在反映了您的最新需求。感谢您的提醒@Dimitre Novatchev,我刚刚更新了问题。因此我尝试了您的解决方案,非常棒。但有一件事,xml似乎被重新格式化为两行(失去了原始格式)。我想知道它是否可以在删除重复项的同时保留格式?@jonah_w,我不知道你所说的“原始格式”是什么意思。转换的结果具有问题中提供的XML文档格式。抱歉,我再次检查了。这是我在代码中犯的错误。生成的XML非常完美。:)谢谢你的回答。@Dimitre Novatchev我应该提到每个条目都有自己独立的@jonah\u w,谢谢——你必须在问题中提供想要的结果。我编辑了答案,现在它反映了你的最新要求。谢谢你提醒@Dimitre Novatchev,我刚刚更新了问题。所以我尝试了你的解决方案在上,这真是太棒了。不过有一件事,xml似乎被重新格式化为两行(失去了原始格式)。我想知道它是否可以在删除重复项的同时保留格式?@jonah_w,我不知道你所说的“原始格式”是什么意思。转换的结果具有问题中提供的XML文档格式。抱歉,我再次检查。这是我在代码中犯的错误。生成的XML非常完美。:)感谢@JJoao我刚刚尝试了这种方法。生成的xml似乎删除了xml声明和命名空间。感谢@JJoao我刚刚尝试了这种方法。生成的xml似乎删除了xml声明和命名空间。