merge two elements using xslt based on attribute values

帅比萌擦擦* 提交于 2019-12-02 10:03:58

问题


This is how my source file looks like:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<book>
    <mbean code="org.book.mybooks"  name="mycompany.props.jndi:name=mybookprops">   
        <attribute name="bookprops">
            abc.mybook.onebook=@Value@
            def.mybook.twobook=@Value@
            ghi.myebook.threebook=@Value@
        </attribute>
    </mbean>
    <book>
        <mbean code="org.book.mybooks"  name="mycompany.props.jndi:name=mybookprops">   
            <attribute name="bookprops">
            abc.mybook.onebook=@New_Value@
            def.mybook.twobook=@New_Value@
            ghi.myebook.fourbook=@Value@

            </attribute>
        </mbean>
    </book>
</book>

I am looking to get merge two attributes to one and copy all the matching lines with new variable @New_Value@ and copy all other non matching lines to the end of the file.

This problem is pretty much similar to the question that i have posted earlier merge parent and child attributes using xslt based on attribute values only difference is the format of the content in the XML file.

Based on the solution that was provided in the above URL, I have tweaked my xsl to get work this new XML file, here is the xsl file:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:jndi="urn:jboss:jndi-binding-service:1.0"  >
    <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" /> 
    <xsl:template match="book/book"> 
        <book>
            <mbean code="org.book.mybooks" name="mycompany.props.jndi:name=mybookprops">    
                <attribute name="bookprops">
                    <xsl:copy-of select="mbean/attribute/node()"/>
                    <xsl:call-template name="Mbean">
                        <xsl:with-param name="bindings" select="book/mbean/attribute"/>
                    </xsl:call-template> 
                </attribute>
            </mbean>
        </book>
    </xsl:template>  

    <xsl:template name="Mbean">
        <xsl:param name="bindings"/>
        <xsl:for-each select="/book/mbean/attribute/node()">
            <xsl:variable name="currentBinding" select="self::node()"/>  
            <xsl:if test="not(node()[. = $bindings])">
                <xsl:copy-of select="self::node()"/>
            </xsl:if>                        
        </xsl:for-each>
    </xsl:template>
    <xsl:template match="text()"/>
</xsl:stylesheet>

But somehow i was not able to get the expected result, following is the expected result that i am looking for:

<book>
    <mbean code="org.book.mybooks"  name="mycompany.props.jndi:name=mybookprops">   
        <attribute name="bookprops">
            abc.mybook.onebook=@New_Value@
            def.mybook.twobook=@New_Value@
            ghi.myebook.threebook=@Value@
            ghi.myebook.fourbook=@Value@
        </attribute>
    </mbean>
</book>

回答1:


It's a bit ugly but it does what you want and sorry if the first time did not understand well.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:jndi="urn:jboss:jndi-binding-service:1.0"  >
    <xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes" /> 
    <xsl:template match="book/book"> 
        <book>
            <mbean code="org.book.mybooks" name="mycompany.props.jndi:name=mybookprops">   
            <attribute name="bookprops">                 
                    <xsl:copy-of select="mbean/attribute/text()"/>
                    <xsl:call-template name="Mbean">
                        <xsl:with-param name="bindings" select="mbean/attribute"/>
                        <xsl:with-param name="bindingsP" select="/book/mbean/attribute/text()"/>
                    </xsl:call-template>     
             </attribute>           
            </mbean>
        </book>
    </xsl:template>   
    <xsl:template name="Mbean">
        <xsl:param name="bindings"/>
        <xsl:param name="bindingsP"/>          
            <xsl:choose>
                    <xsl:when test="contains($bindingsP,'@Value@')">
                          <xsl:if test="not(contains(substring-before($bindingsP,'@Value@'),'@Value@')) and not(contains(substring-before($bindingsP,'@Value@'),'@New_Value@')) and not(contains($bindings,concat(substring-before($bindingsP,'@Value@'),'@Value@')))">
                                <xsl:copy-of select="concat(substring-before($bindingsP,'@Value@'),'@Value@')"/>
                                <xsl:call-template name="Mbean">
                                   <xsl:with-param name="bindings" select="$bindings"/>
                                   <xsl:with-param name="bindingsP" select="substring-after($bindingsP,'@Value@')"/>
                                </xsl:call-template>
                            </xsl:if>                          
                    </xsl:when>
                    <xsl:when test="contains($bindingsP,'@New_Value@')">
                           <xsl:if test="not(contains(substring-before($bindingsP,'@Value@'),'@Value@')) and not(contains(substring-before($bindingsP,'@Value@'),'@New_Value@')) and not(contains($bindings,concat(substring-before($bindingsP,'@New_Value@'),'@New_Value@')))">
                                <xsl:copy-of select="concat(substring-before($bindingsP,'@New_Value@'),'@New_Value@')"/>
                                <xsl:call-template name="Mbean">
                                   <xsl:with-param name="bindings" select="$bindings"/>
                                   <xsl:with-param name="bindingsP" select="substring-after($bindingsP,'@New_Value@')"/>
                                </xsl:call-template>
                            </xsl:if>       

                    </xsl:when>
            </xsl:choose>    

    </xsl:template>

    <xsl:template match="text()"/>
</xsl:stylesheet>


来源:https://stackoverflow.com/questions/18450728/merge-two-elements-using-xslt-based-on-attribute-values

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!