【问题标题】:remove duplicate nodes from XML file (XSLT transformation)从 XML 文件中删除重复节点(XSLT 转换)
【发布时间】:2018-11-22 21:05:09
【问题描述】:

如果有人可以帮助我创建 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>    

【问题讨论】:

  • 到目前为止你有什么尝试?
  • 不清楚要删除哪些元素。 Data 属性似乎只存在于 FileHash 元素上,前两个似乎具有相同的 Data 值,那么为什么第二个没有在想要的输出中删除?至于PublisherName属性,如果FilePublisherCondition元素上的重复属性值是删除祖先FilePublisherRule的条件,我想知道一个例子是否足以解释规则。一个FilePublisherRule 可以有多个FilePublisherCondition 后代吗?
  • 有很多关于删除重复的帖子 - 如果您搜索“分组”,则更多。这些问题在 XSLT 2.0 中比在 1.0 中更容易解决,因此首先要确定您是否已经在使用 XSLT 2.0,或者您是否能够安装 XSLT 2.0 处理器。 (请用“xslt 1.0”或“xslt 2.0”标记 XSLT 问题,以节省大家的精力。)
  • @MichaelKay,不幸的是我没有使用 xslt 语言的经验,我正在使用 MS 进程 microsoft.com/en-us/download/details.aspx?id=21714,我想它是第 2 版
  • @MartinHonnen,我已将我的示例更正为更清晰,FilePublisherRule 只有单个 FilePublisherCondition 后代

标签: xml xslt


【解决方案1】:

您关于消除重复的FileHash 元素的解决方案是正确的, 虽然它可以稍微简化(见下面我的代码)。

要消除包含重复PublisherName 属性的FilePublisherRule 元素, 我们必须这样做:

  1. 创建一个key(我叫它kPubl),匹配FilePublisherCondition, 使用@PublisherName
  2. 编写一个匹配FilePublisherRule的模板,并在其中:
    • Conditions/FilePublisherCondition保存在一个变量下(我称之为 fpCond)
    • 检查generate-id$fpCond 的相等性以及读取的第一个键 来自kPubl,为$fpCond/@PublisherName
    • 如果它们相等,则复制当前元素(我使用了copyapply-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

【讨论】:

  • 非常适合我!非常感谢。
【解决方案2】:

要根据孙子的属性消除 FilePublisherRule 重复项,您只需添加一个键和使用该键的另一个空模板:

  <xsl:key name="publisherName" match="FilePublisherRule" use="Conditions/FilePublisherCondition/@PublisherName"/>

  <xsl:template match="FilePublisherRule[not(generate-id() = generate-id(key('publisherName', Conditions/FilePublisherCondition/@PublisherName)[1]))]"/>

https://xsltfiddle.liberty-development.net/bFDb2Dj

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多