问题
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