使用相同级别的相同名称的节点转换XML

时间:2014-05-26 23:13:45

标签: xml xslt

我试图用XSLT解析XML文档,但我真的很新手。

我已经生成了这样的XML文档:

<DOC>
<FORM>VI0CBCNE</FORM>
<DAY>23</DAY>
<FORM>AP0002</FORM>
<BAR>109130000005</BAR>
<CODBAR>109130000005</CODBAR>
<FORM>AP0001</FORM>
</DOC>

我想把它变成这样的东西:

<DOC>
  <DOC_FORM>
    <FORM>VI0CBCNE</FORM>
    <DAY>23</DAY>
  </DOC_FORM>
  <DOC_FORM>
    <FORM>AP0002</FORM>
    <BAR>109130000005</BAR>
    <CODBAR>109130000005</CODBAR>
  </DOC_FORM>
  <DOC_FORM>
    <FORM>AP0001</FORM>
  </DOC_FORM>
</DOC>

FORM节点的数量可能会改变,也就是FORMS之间的节点数。

我甚至没有解决方案,所以我无法分享我的XSL。有人能帮我解决一下我能做什么的线索吗? 我使用的是apache camel和一个XSLT 2.0处理器。

2 个答案:

答案 0 :(得分:0)

以下XSLT将生成您的结果。 局限性。只有已定义的节点将按照XSLT中指定的顺序进行映射,而不是源的顺序。

<?xml version="1.0" encoding="UTF-16"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" exclude-result-prefixes="msxsl" version="1.0">
  <xsl:output omit-xml-declaration="yes" method="xml" version="1.0" />
  <xsl:template match="/">
    <xsl:apply-templates select="/DOC" />
  </xsl:template>
  <xsl:template match="/DOC">
    <DOC>
      <xsl:for-each select="FORM">
        <xsl:variable name="pos" select="position()" />
        <DOC_FORM>
          <FORM>
            <xsl:value-of select="./text()" />
          </FORM>
          <xsl:if test="//BAR[$pos = count(preceding-sibling::FORM)]">
            <BAR>
              <xsl:value-of select="//BAR[$pos = count(preceding-sibling::FORM)]/text()" />
            </BAR>
          </xsl:if>
          <xsl:if test="//CODBAR[$pos = count(preceding-sibling::FORM)]">
            <CODBAR>
              <xsl:value-of select="../CODBAR[$pos = count(preceding-sibling::FORM)]/text()" />
            </CODBAR>
          </xsl:if>
          <xsl:if test="//DAY[$pos = count(preceding-sibling::FORM)]">
            <DAY>
              <xsl:value-of select="../DAY[$pos = count(preceding-sibling::FORM)]/text()" />
            </DAY>
          </xsl:if>
        </DOC_FORM>
      </xsl:for-each>
    </DOC>
  </xsl:template>
</xsl:stylesheet>

答案 1 :(得分:0)

由于您使用的是XSL 2.0,因此您可以利用xsl:for-each-group元素及其group-starting-with选项:

<xsl:stylesheet version="2.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/DOC">
    <xsl:copy>
        <xsl:for-each-group select="*" group-starting-with="FORM">
            <DOC_FORM>
                <xsl:copy-of select="current-group()" />
            </DOC_FORM>
        </xsl:for-each-group>
    </xsl:copy>
</xsl:template>

</xsl:stylesheet>