拆分节点并将它们分配给变量进行匹配

时间:2013-08-28 13:42:15

标签: xml regex xslt xslt-1.0 xslt-2.0

这个问题类似于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-->

目标是:

将两个元素组合到一个元素,如果两个元素具有相似的节点,节点的值不同,则用第二个属性节点替换第一个属性节点的值。

我想到的程序:

  1. 对第一个和第二个元素的节点进行排序。
  2. 拆分第一个元素的节点并将其分配给变量。示例:第一个元素的节点abc.mybook.onebook = @ Value @被拆分为两个并将它们分配给变量varaible1 = abc.mybook.onebook和varaible2 = @ Value @。
  3. Simillar方式拆分第二个元素的节点并将它们分配给变量。第二个元素abc.mybook.onebook = @ New_Value @的示例节点被拆分为两个并将它们分配给变量,如varaible3 = abc.mybook.onebook和varaible4 = @ New_Value @。
  4. 现在将第一个元素变量与第二个元素变量匹配。示例:如果variable1等于variable3,则将variable2替换为varaible4;否则复制第一个元素节点并复制第二个元素节点。
  5. 这可以在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>
    

1 个答案:

答案 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>&#10;</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, '=', ., '&#10;')"/>
</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-->