带分组或XPath的XSLT1.0

时间:2017-06-06 00:57:17

标签: xml xslt xpath

我的源文件xml如下:

> @fluent_user_ids
 => [2, 4, 5, 5, 6, 9, 8, 8, 7, 7, 12, 165, 166, 171, 174, 176, 177, 142, 206, 207, 208, 209, 214, 215, 216, 10, 229, 230, 232, 234, 236, 237, 238, 233, 233, 240, 241, 242, 243, 244, 250, 251, 252, 253, 254, 255, 256, 257, 258, 260, 261, 262, 264, 265, 266, 267, 268, 269, 270, 273, 274, 276, 233] 

 > @nonfluent_user_ids
 => [2, 5, 11, 166, 142, 13, 206, 207, 208, 209, 214, 215, 216, 171, 10, 229, 230, 231, 232, 234, 236, 237, 238, 233, 239, 240, 241, 242, 243, 244, 250, 251, 252, 253, 254, 255, 256, 257, 258, 260, 261, 262, 264, 265, 266, 267, 268, 269, 270, 273, 274, 276] 

> @nonfluent_user_ids & @fluent_users_ids

TypeError: no implicit conversion of nil into Array
    from (irb):27:in `&'

我需要做出如下最终结果。它将基于<root> <bp> <id>999</id> <role>FL01</role> <comp/> </bp> <bp> <id>999</id> <role>FL00</role> <comp>123</comp> </bp> <bp> <id>999</id> <role>FL02</role> <comp>456</comp> </bp> <bp> <id>888</id> <role>FL01</role> <comp/> </bp> <bp> <id>888</id> <role>FL00</role> <comp>123</comp> </bp> <bp> <id>888</id> <role>FL02</role> <comp>456</comp> </bp> </root> <comp>进行拆分。但是,<id>没有值<bp> <comp>需要添加到每个拆分中。

<role>

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

修改1:更新的答案以反映新的要求

(请注意,我假设您将<bp>元素包含在根级元素中。)

如果每个<bp>的孩子的顺序并不重要,那么这个XSLT:

<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="1.0">
  <xsl:output method="xml" omit-xml-declaration="no" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="kBpByCompAndId" match="bp" use="concat(comp, '+', id)"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="/*">
    <root>
      <xsl:apply-templates
        select="*[normalize-space(comp)][
          generate-id() = generate-id(
            key('kBpByCompAndId', concat(comp, '+', id))[1]
          )
        ]"/>
    </root>
  </xsl:template>

  <xsl:template match="bp">
    <bp>
      <xsl:apply-templates
        select="*|key('kBpByCompAndId', concat('+', id))/role"/>
    </bp>
  </xsl:template>

</xsl:stylesheet>

...将产生功能相同的结果:

<?xml version="1.0"?>
<root>
  <bp>
    <role>FL01</role>
    <id>999</id>
    <role>FL00</role>
    <comp>123</comp>
  </bp>
  <bp>
    <role>FL01</role>
    <id>999</id>
    <role>FL02</role>
    <comp>456</comp>
  </bp>
  <bp>
    <role>FL01</role>
    <id>888</id>
    <role>FL00</role>
    <comp>123</comp>
  </bp>
  <bp>
    <role>FL01</role>
    <id>888</id>
    <role>FL02</role>
    <comp>456</comp>
  </bp>
</root>

作为参考,这个XSLT使用了一种名为Muenchian Grouping的分组技术;因为您不熟悉XSLT,所以这是一个很好的技术,可以放入您的工具包中。