这个问题类似于merge two elements using xslt based on attribute values,但试图以不同的方式将其置于可以更好理解的地方。
我有一个xml文件,其中包含两个名称相同的元素,但第二个元素是第一个元素的一部分。 例如:
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- This is first element-->
<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>
<!--This is second element and is part of first element-->
<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><!--closing tag of second element-->
</book><!--closing tag of first element-->
目标是:
将两个元素组合到一个元素,如果两个元素具有相似的节点,节点的值不同,则用第二个属性节点替换第一个属性节点的值。
我想到的程序:
这可以在shell或bash中非常容易地完成,但由于要求与xslt有关,我试图找出它是如何实现的。
我期待的最终输出是:
<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>
答案 0 :(得分:0)
我会使用analyze-string
提取部分,然后你可以分组:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:mf="http://example.com/mf"
exclude-result-prefixes="xs mf">
<xsl:function name="mf:props" as="element(value)*">
<xsl:param name="input" as="xs:string"/>
<xsl:analyze-string select="$input" regex="(\S+)=(\S+)">
<xsl:matching-substring>
<value key="{regex-group(1)}"><xsl:value-of select="regex-group(2)"/></value>
</xsl:matching-substring>
</xsl:analyze-string>
</xsl:function>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* , node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="book[book]/mbean/attribute">
<xsl:copy>
<xsl:copy-of select="@*"/>
<xsl:variable name="props">
<xsl:sequence select="mf:props(.), mf:props(../following-sibling::book/mbean/attribute)"/>
</xsl:variable>
<xsl:text> </xsl:text>
<xsl:for-each-group select="$props/value" group-by="@key">
<xsl:apply-templates select="current-group()[last()]" mode="value-to-prop"/>
</xsl:for-each-group>
</xsl:copy>
</xsl:template>
<xsl:template match="value" mode="value-to-prop">
<xsl:value-of select="concat(' ', @key, '=', ., ' ')"/>
</xsl:template>
<xsl:template match="book/book"/>
</xsl:stylesheet>
Saxon 9.5将您的输入转换为
<?xml version="1.0" encoding="UTF-8"?><!-- This is first element--><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>
<!--This is second element and is part of first element-->
<!--closing tag of second element-->
</book><!--closing tag of first element-->