xml - 从 XML 文件中删除重复节点(XSLT 转换)
问题描述
如果有人可以帮助我创建 xslt 以根据重复属性的值从 XML 中删除重复节点,我将不胜感激。在下面的示例中,属性是 PublisherName 和 Data
输入
<RuleCollection>
<FilePublisherRule Id="1">
<Conditions>
<FilePublisherCondition PublisherName="O=Vendor1">
<BinaryVersionRange LowSection="*" HighSection="*" />
</FilePublisherCondition>
</Conditions>
</FilePublisherRule>
<FilePublisherRule Id="2">
<Conditions>
<FilePublisherCondition PublisherName="O=Vendor2">
<BinaryVersionRange LowSection="*" HighSection="*" />
</FilePublisherCondition>
</Conditions>
</FilePublisherRule>
<FilePublisherRule Id="3">
<Conditions>
<FilePublisherCondition PublisherName="O=Vendor1">
<BinaryVersionRange LowSection="*" HighSection="*" />
</FilePublisherCondition>
</Conditions>
</FilePublisherRule>
<FileHashRule Id="10">
<Conditions>
<FileHashCondition>
<FileHash Type="SHA256" Data="0xF11BD15D6A565071AED8D3581012C5B5EE0AB46795CEF4ECD712F7572A3DBE36" SourceFileName="_IU14D2N.TMP" SourceFileLength="0" />
<FileHash Type="SHA256" Data="0xF11BD15D6A565071AED8D3581012C5B5EE0AB46795CEF4ECD712F7572A3DBE36" SourceFileName="UNINS000.EXE" SourceFileLength="0" />
<FileHash Type="SHA256" Data="0x5831F348B9B2744F56631CFB2FCAB676BD8B9D3EE407A2DE2C66BC3C395A9E73" SourceFileName="CO.EXE" SourceFileLength="0" />
<FileHash Type="SHA256" Data="0x4BA8285055A9CF8EE146F738DC8526CCD1E509B03984FE1914A6826C7CD530EE" SourceFileName="SETUPCO.EXE" SourceFileLength="0" />
<FileHash Type="SHA256" Data="0x4BA8285055A9CF8EE146F738DC8526CCD1E509B03984FE1914A6826C7CD530EE" SourceFileName="SETUPDAR.EXE" SourceFileLength="0" />
</FileHashCondition>
</Conditions>
</FileHashRule>
<RuleCollection/>
我需要
<RuleCollection>
<FilePublisherRule Id="1">
<Conditions>
<FilePublisherCondition PublisherName="O=Vendor1">
<BinaryVersionRange LowSection="*" HighSection="*" />
</FilePublisherCondition>
</Conditions>
</FilePublisherRule>
<FilePublisherRule Id="2">
<Conditions>
<FilePublisherCondition PublisherName="O=Vendor2">
<BinaryVersionRange LowSection="*" HighSection="*" />
</FilePublisherCondition>
</Conditions>
</FilePublisherRule>
<FileHashRule Id="10">
<Conditions>
<FileHashCondition>
<FileHash Type="SHA256" Data="0xF11BD15D6A565071AED8D3581012C5B5EE0AB46795CEF4ECD712F7572A3DBE36" SourceFileName="UNINS000.EXE" SourceFileLength="0" />
<FileHash Type="SHA256" Data="0x5831F348B9B2744F56631CFB2FCAB676BD8B9D3EE407A2DE2C66BC3C395A9E73" SourceFileName="CO.EXE" SourceFileLength="0" />
<FileHash Type="SHA256" Data="0x4BA8285055A9CF8EE146F738DC8526CCD1E509B03984FE1914A6826C7CD530EE" SourceFileName="SETUPCO.EXE" SourceFileLength="0" />
</FileHashCondition>
</Conditions>
</FileHashRule>
<RuleCollection/>
我检查了一些已经存在的案例,似乎我需要在 xslt 中使用一些模板并使用 Munechian 分组,但我没有经验。
我已使用此 xslt 处理删除重复的 FileHash 节点
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kPropertyByName" match="FileHash" use="@Data"/>
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<xsl:template
match="FileHash[
not(
generate-id() =
generate-id(key('kPropertyByName', @Data)[1])
)
]"/>
</xsl:stylesheet>
另外我的输出文件比原始文件大,为什么?我需要更小。我想下一步是添加第二个模板来处理基于 PublishedName 值的 FilePublisherRule 节点删除
我添加了第二个模板
<xsl:template
match="FileHash[
not(
generate-id() =
generate-id(key('kPropertyByName', @Data)[1])
)
]"/>
<xsl:template
match="FilePublisherCondition[
not(
generate-id() =
generate-id(key('kProperty1ByName', @PublisherName)[1])
)
复制节点 FilePublisherCondition 删除但父节点离开
<FilePublisherRule Id="0355cba7-7d4a-4a74-9579-8d2192fa0514" Name="Signed by O=ADOBE SYSTEMS INCORPORATED, L=SAN JOSE, S=CALIFORNIA, C=US" Description="" UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions>
<FilePublisherCondition PublisherName="O=ADOBE SYSTEMS INCORPORATED, L=SAN JOSE, S=CALIFORNIA, C=US" ProductName="*" BinaryName="*">
<BinaryVersionRange LowSection="*" HighSection="*"></BinaryVersionRange>
</FilePublisherCondition>
</Conditions>
</FilePublisherRule>
<FilePublisherRule Id="0355cba7-7d4a-4a74-9579-8d2192fa0514" Name="Signed by O=ADOBE SYSTEMS INCORPORATED, L=SAN JOSE, S=CALIFORNIA, C=US" Description="" UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions></Conditions>
</FilePublisherRule>
<FilePublisherRule Id="0355cba7-7d4a-4a74-9579-8d2192fa0514" Name="Signed by O=ADOBE SYSTEMS INCORPORATED, L=SAN JOSE, S=CALIFORNIA, C=US" Description="" UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions></Conditions>
</FilePublisherRule>
<FilePublisherRule Id="e9a23377-81af-41dd-b65d-d8f45c7eac7f" Name="myAgent (O=FLEXERA SOFTWARE LLC, L=SCHAUMBURG, S=ILLINOIS, C=US)" Description="myAgent (6.2.1.172)" UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions>
<FilePublisherCondition PublisherName="O=FLEXERA SOFTWARE LLC, L=SCHAUMBURG, S=ILLINOIS, C=US" ProductName="*" BinaryName="*">
<BinaryVersionRange LowSection="*" HighSection="*"></BinaryVersionRange>
</FilePublisherCondition>
</Conditions>
</FilePublisherRule>
<FilePublisherRule Id="e9a23377-81af-41dd-b65d-d8f45c7eac7f" Name="myAgent (O=FLEXERA SOFTWARE LLC, L=SCHAUMBURG, S=ILLINOIS, C=US)" Description="myAgent (6.2.1.172)" UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions></Conditions>
</FilePublisherRule>
<FileHashRule Id="c4232cc1-563b-4fa7-84da-19331af01de4" Name="communication clients" Description="" UserOrGroupSid="S-1-1-0" Action="Allow">
<Conditions>
解决方案
您关于消除重复FileHash
元素的解决方案是正确的,尽管它可以有点简化(请参阅下面的代码)。
为了消除FilePublisherRule
包含重复PublisherName
属性的元素,我们必须做类似的事情:
- 创建一个
key
(我称之为kPubl
),匹配FilePublisherCondition
,使用@PublisherName
。 - 编写一个模板匹配
FilePublisherRule
并在其中:- 保存
Conditions/FilePublisherCondition
在变量下(我称之为fpCond
) generate-id
检查for$fpCond
和从kPubl
, for读取的第一个键是否相等$fpCond/@PublisherName
。- 如果它们相等,则复制当前元素(我使用
copy
andapply-templates
,就像在标识模板中一样)。 - 否则什么都不做(跳过这个元素)。
- 保存
所以整个 XSLT 脚本可以如下:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kData" match="FileHash" use="@Data"/>
<xsl:key name="kPubl" match="FilePublisherCondition" use="@PublisherName"/>
<xsl:template match="@*|node()">
<xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy>
</xsl:template>
<xsl:template match="FileHash[generate-id() !=
generate-id(key('kData', @Data)[1])]"/>
<xsl:template match="FilePublisherRule">
<xsl:variable name="fpCond" select="Conditions/FilePublisherCondition"/>
<xsl:if test="generate-id($fpCond) = generate-id(key('kPubl', $fpCond/@PublisherName)[1])">
<xsl:copy><xsl:apply-templates select="@* | node()"/></xsl:copy>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
有关工作示例,请参见http://xsltransform.net/6qaFCEf
推荐阅读
- bash - 如何使用 bash 从 log_file.txt 中提取数据
- sql - MS SQL Server - 如何将所有存储过程从我的机器导出到我的朋友机器?
- android - 如何监听 canGoBack() 和 canGoForward()?
- php - 如何修复更新 Google 电子表格时出现的错误
- centos7 - centos7 Cockpit 176 无法添加远程主机
- sql - 使用 SQL 插入数据
- ios - 按下听写(语音转文本)按钮时不会触发 UIKeyboardWillChangeFrameNotification
- html - CSS Margin 仅适用于 chrome
- mysql - Mysql Workbench导入数据SQL报错1142
- swift - 您可以严格通用类型或给一个参数多于一种类型吗?