【问题标题】:removing duplicates from xml file use xslt使用 xslt 从 xml 文件中删除重复项
【发布时间】:2013-08-05 13:24:38
【问题描述】:

这是一个示例,其中我有两个具有相同名称的 <mbean> 部分,但这些部分中的属性不同,我想合并这两个 <mbean> 部分并且重复的属性必须替换为最新的被添加到<mbean> 部分的底部。

        <mbean code="org.jboss.naming.JNDIBindingServiceMgr"
        name="abc.myconfig.jndi:name=myconfigAppPartitionJNDI">
        <attribute name="BindingsConfig" serialDataType="jbxb">
            <jndi:bindings
                xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
                xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">                   
                <jndi:binding
                    name="myabc/myconfig/myservice/myabcservice">
                    <jndi:value type="java.lang.String">
                        old-value
                    </jndi:value>
                </jndi:binding>
                <jndi:binding name="myabc/myconfig/myabcdefService/myabcdefServiceUrl">
                      <jndi:value type="java.lang.String">
                            @myabcdefService.myabcdefServiceUrl@
                      </jndi:value>
                </jndi:binding>
            </jndi:bindings> 
        </attribute>
    </mbean>
    <mbean code="org.jboss.naming.JNDIBindingServiceMgr"
        name="abc.myconfig.jndi:name=myconfigAppPartitionJNDI">
        <attribute name="BindingsConfig" serialDataType="jbxb">
            <jndi:bindings
                xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
                xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">                   
                <jndi:binding
                    name="myabc/myconfig/myservice/myabcservice">
                    <jndi:value type="java.lang.String">
                        new-value
                    </jndi:value>
                </jndi:binding>
                <jndi:binding name="myabc/myconfig/myabcdefService/myabcdefServiceUrl">
                      <jndi:value type="java.lang.String">
                            @myabcdefService.myabcdefServiceUrl@
                      </jndi:value>
                </jndi:binding>
                <jndi:binding name="myabc/myconfig/myabcdefService/myabcFileNet">
                      <jndi:value type="java.lang.String">
                            @myabcdefService.myabcFileNet@
                      </jndi:value>
                </jndi:binding>
            </jndi:bindings> 
        </attribute>
    </mbean>

预期输出为:

                <mbean code="org.jboss.naming.JNDIBindingServiceMgr"
        name="abc.myconfig.jndi:name=myconfigAppPartitionJNDI">
        <attribute name="BindingsConfig" serialDataType="jbxb">
            <jndi:bindings
                xmlns:xs="http://www.w3.org/2001/XMLSchema-instance"
                xmlns:jndi="urn:jboss:jndi-binding-service:1.0"
                xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">                   
                <jndi:binding name="myabc/myconfig/myabcdefService/myabcdefServiceUrl">
                      <jndi:value type="java.lang.String">
                            @myabcdefService.myabcdefServiceUrl@
                      </jndi:value>
                </jndi:binding>
                <jndi:binding
                    name="myabc/myconfig/myservice/myabcservice">
                    <jndi:value type="java.lang.String">
                        new-value
                    </jndi:value>
                </jndi:binding>
                <jndi:binding name="myabc/myconfig/myabcdefService/myabcFileNet">
                      <jndi:value type="java.lang.String">
                            @myabcdefService.myabcFileNet@
                      </jndi:value>
                </jndi:binding>
            </jndi:bindings> 
        </attribute>
    </mbean>

【问题讨论】:

    标签: xml replace xslt-1.0 mbeans


    【解决方案1】:

    您需要使用 Muenchian Method 来删除重复项

    XSLT:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>
        <xsl:strip-space elements="*"/>
        <xsl:key name="mbeanName" match="//mbean/@name" use="."/>
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="mbean[not(generate-id(@name) = generate-id(key('mbeanName', @name)[1]))]"/>
    </xsl:stylesheet>
    

    XML:

    <?xml version="1.0" encoding="UTF-8"?>
    <root>
        <mbean code="org.jboss.naming.JNDIBindingServiceMgr" name="abc.myconfig.jndi:name=myconfigAppPartitionJNDI">
            <attribute name="BindingsConfig" serialDataType="jbxb">
                <jndi:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xmlns:jndi="urn:jboss:jndi-binding-service:1.0" xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">
                    <jndi:binding name="myabc/myconfig/myservice/myabcservice">
                        <jndi:value type="java.lang.String">
                            old-value
                        </jndi:value>
                    </jndi:binding>
                    <jndi:binding name="myabc/myconfig/myabcdefService/myabcdefServiceUrl">
                        <jndi:value type="java.lang.String">
                                @myabcdefService.myabcdefServiceUrl@
                          </jndi:value>
                    </jndi:binding>
                </jndi:bindings>
            </attribute>
        </mbean>
        <mbean code="org.jboss.naming.JNDIBindingServiceMgr" name="abc.myconfig.jndi:name=myconfigAppPartitionJNDI">
            <attribute name="BindingsConfig" serialDataType="jbxb">
                <jndi:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xmlns:jndi="urn:jboss:jndi-binding-service:1.0" xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">
                    <jndi:binding name="myabc/myconfig/myservice/myabcservice">
                        <jndi:value type="java.lang.String">
                            new-value
                        </jndi:value>
                    </jndi:binding>
                    <jndi:binding name="myabc/myconfig/myabcdefService/myabcdefServiceUrl">
                        <jndi:value type="java.lang.String">
                                @myabcdefService.myabcdefServiceUrl@
                          </jndi:value>
                    </jndi:binding>
                    <jndi:binding name="myabc/myconfig/myabcdefService/myabcFileNet">
                        <jndi:value type="java.lang.String">
                                @myabcdefService.myabcFileNet@
                          </jndi:value>
                    </jndi:binding>
                </jndi:bindings>
            </attribute>
        </mbean>
    </root>
    

    输出:

    <root>
        <mbean code="org.jboss.naming.JNDIBindingServiceMgr" name="abc.myconfig.jndi:name=myconfigAppPartitionJNDI">
            <attribute name="BindingsConfig" serialDataType="jbxb">
                <jndi:bindings xmlns:jndi="urn:jboss:jndi-binding-service:1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:schemaLocation="urn:jboss:jndi-binding-service:1.0 resource:jndi-binding-service_1_0.xsd">
                    <jndi:binding name="myabc/myconfig/myservice/myabcservice">
                        <jndi:value type="java.lang.String">
                            old-value
                        </jndi:value>
                    </jndi:binding>
                    <jndi:binding name="myabc/myconfig/myabcdefService/myabcdefServiceUrl">
                        <jndi:value type="java.lang.String">
                                @myabcdefService.myabcdefServiceUrl@
                          </jndi:value>
                    </jndi:binding>
                </jndi:bindings>
            </attribute>
        </mbean>
    </root>
    

    更新的 XSLT:

    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output omit-xml-declaration="yes" indent="yes"/>
        <xsl:strip-space elements="*"/>
        <xsl:key name="mbeanName" match="//mbean/@name" use="."/>
        <xsl:key name="mbeanCount" match="//mbean[generate-id(@name) = generate-id(key('mbeanName', @name)[1])]" use="count(.)"/>
        <xsl:template match="node()|@*">
            <xsl:copy>
                <xsl:apply-templates select="node()|@*"/>
            </xsl:copy>
        </xsl:template>
        <xsl:template match="mbean[count(. | key('mbeanCount', /mbean/@name))]" />
    </xsl:stylesheet>
    

    【讨论】:

    • @Charan,预期的输出与您的输出不同:&lt;jndi:binding name="myabc/myconfig/myservice/myabcservice"&gt; &lt;jndi:value type="java.lang.String"&gt; new-value &lt;/jndi:value&gt; &lt;/jndi:binding&gt;
    • 当您按名称收集节点 mbean 时,muenchian 方法不会只给您同名节点的第一个节点吗?如果您还索引 jndi:value 节点并使用相同的技术在 mbean 下输出它们会怎样?
    • @Jeremy 可以举个例子吗?
    • 评论空间没有足够的字符来解释我的想法,所以我会把它作为答案,但请记住,这是未经测试的,只是一种技术发生在我身上。您必须使用它才能使其正常工作。
    • @phani:用新的 XSLT 更新了答案。希望这会对你有所帮助。
    【解决方案2】:

    Siva Charan 的答案中的 mbean 模板消除了 @name 重复的 mbean 元素,因此您要保留该部分。

    我在想也许你可以添加一个模板匹配 mbean,它收集了父节点具有相同名称的所有属性节点。因此,在 mbean 模板下,您将选择类似 ../mbean/attribute[../@name = current()/@name] 的 xpath,假设您将其设置为变量 $attributes。然后硬编码&lt;attributes&gt;&lt;jndi:bindings&gt;,然后输出所有$attributes/jndi:bindings/jndi:binding 使得jndi:value 是唯一的。所以为此,我猜你会设置一个匹配 jndi:value 的键,然后创建一个类似于 jndi:binding[generate-id(jndi:value) = generate-id(key('jndivals', jndi:value)[1])] 的 xpath

    对不起,这太粗略了,但就像我说的,这些只是我没有测试过的想法。我希望这至少会有所帮助,而且我不会完全走错方向。

    【讨论】:

    • 用新的 XSLT 更新了我的答案。看看吧。
    • @Jeremy,我喜欢这个主意。由于时间关系,我现在选择charan解决方案。
    猜你喜欢
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多