XSLT muenchian在密钥的帮助下进行分组

时间:2015-05-06 07:29:35

标签: xml xslt xslt-1.0

我想找到一个解决方案,到目前为止一无所获。 我想要实现的是转换

Input:
<?xml version="1.0" encoding="utf-8"?>
<Root>
    <Query>
        <ID>123123</ID>
        <NameOfTeam>Team1</NameOfTeam>
        <RaisingYear>2014</RaisingYear>
        <Brief>N/A</Brief>
        <TeamMembers>
          <Member>
            <Name>Person1</Name>
            <Role>Role1</Role>
          </Member>
          <Member>
            <Name>Person2</Name>
            <Role>Role2</Role>
          </Member>
          <Member>
            <Name>N/A</Name>
            <Role>
              Role4
            </Role>
          </Member>
        </TeamMembers>
        <TeamMembers2>
          <Member>
            <Name>Person3</Name>
            <Role>Role3</Role>
          </Member>
          <Member>
            <Name>Person4</Name>
            <Role>Role4</Role>
          </Member>
          <Member>
            <Name>Person5</Name>
            <Role>Role5</Role>
          </Member>
        </TeamMembers2>
        <Projects>
          <Project>NISAR</Project>
        </Projects>
        <Documents>
          <Document>
            <Language>en</Language>
            <LanguageName>English</LanguageName>
            <GeneralInfo>Useless project</GeneralInfo>
            <Authors>
                <Author>Author1</Author>
                <Author>Author2</Author>
            </Authors>
          </Document>
        </Documents>
      </Query>
      <Query>
        <ID>123124</ID>
        <NameOfTeam>Team2</NameOfTeam>
        <RaisingYear>2012</RaisingYear>
        <Brief>N/A</Brief>
        <TeamMembers>
          <Member>
            <Name>Person6</Name>
            <Role>Role1</Role>
          </Member>
          <Member>
            <Name>Person7</Name>
            <Role>Role2</Role>
          </Member>
          <Member>
            <Name>Person8</Name>
            <Role>Role3</Role>
          </Member>
        </TeamMembers>
        <TeamMembers2>
          <Member>
            <Name>Person3</Name>
            <Role>Role3</Role>
          </Member>
          <Member>
            <Name>Person4</Name>
            <Role>Role4</Role>
          </Member>
          <Member>
            <Name>Person5</Name>
            <Role>Role5</Role>
          </Member>
        </TeamMembers2>
        <Projects>
          <Project>MissionMars</Project>
        </Projects>
        <Documents>
          <Document>
            <Language>en</Language>
            <LanguageName>English</LanguageName>
            <GeneralInfo> </GeneralInfo>
          </Document>
          <Document>
            <Language>en</Language>
            <LanguageName>English</LanguageName>
            <GeneralInfo>It is a rubbish comment</GeneralInfo>
          </Document>
          <Document>
            <Language>fr</Language>
            <LanguageName>English</LanguageName>
            <GeneralInfo>It is another rubbish comment.</GeneralInfo>
          </Document>
        </Documents>
    </Query>
</Root>

Output:

<?xml version="1.0" encoding="utf-8"?>
<Root>
    <Query>
        <ID>123123</ID>
        <NameOfTeam>Team1</NameOfTeam>
        <RaisingYear>2014</RaisingYear>
        <Brief>N/A</Brief>
        <TeamMembers>
          <Member>
            <Name>Person1</Name>
            <Role>Role1</Role>
          </Member>
          <Member>
            <Name>Person2</Name>
            <Role>Role2</Role>
          </Member>
          <Member>
            <Name>N/A</Name>
            <Role>
              Role4
            </Role>
          </Member>
        </TeamMembers>
        <TeamMembers2>
          <Member>
            <Name>Person3</Name>
            <Role>Role3</Role>
          </Member>
          <Member>
            <Name>Person4</Name>
            <Role>Role4</Role>
          </Member>
          <Member>
            <Name>Person5</Name>
            <Role>Role5</Role>
          </Member>
        </TeamMembers2>
        <Projects>
          <Project>NISAR</Project>
        </Projects>
        <Documents>
          <Document>
            <Language>en</Language>
            <LanguageName>English</LanguageName>
            <GeneralInfo>Useless project</GeneralInfo>
          </Document>
        </Documents>
      </Query>
      <Query>
        <ID>123124</ID>
        <NameOfTeam>Team2</NameOfTeam>
        <RaisingYear>2012</RaisingYear>
        <Brief>N/A</Brief>
        <TeamMembers>
          <Member>
            <Name>Person6</Name>
            <Role>Role1</Role>
          </Member>
          <Member>
            <Name>Person7</Name>
            <Role>Role2</Role>
          </Member>
          <Member>
            <Name>Person8</Name>
            <Role>Role3</Role>
          </Member>
        </TeamMembers>
        <TeamMembers2>
          <Member>
            <Name>Person3</Name>
            <Role>Role3</Role>
          </Member>
          <Member>
            <Name>Person4</Name>
            <Role>Role4</Role>
          </Member>
          <Member>
            <Name>Person5</Name>
            <Role>Role5</Role>
          </Member>
        </TeamMembers2>
        <Projects>
          <Project>MissionMars</Project>
        </Projects>
        <Documents>
          <Document>
            <Language>en</Language>
            <LanguageName>English</LanguageName>
            <GeneralInfo>It is a rubbish comment</GeneralInfo>
          </Document>
          <Document>
            <Language>fr</Language>
            <LanguageName>English</LanguageName>
            <GeneralInfo>It is another rubbish comment.</GeneralInfo>
          </Document>
        </Documents>
    </Query>
</Root>

如果文档标记中的任何详细信息为空,则应合并所有具有相同ID和语言信息的文档,并且只有在可用的情况下,才能将其替换为具有相同语言标记的其他文档标记的信息。 / p>

我正在使用的代码是

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:key name="QueryIDAndLangauge" match="Query" use="concat(ID, '+', Documents/Document/Language)"/>

  <xsl:key name="DocumentsAndLanguage" match="Language" use="Language"/>

  <xsl:key name="DocumentsAndLanguageValue" match="Language" use="concat(ID, '+', .)"/>

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

  <xsl:template match="/*">
    <Root>
      <xsl:apply-templates select=
   "Query[generate-id()
          =
           generate-id(key('QueryIDAndLangauge',
                          concat(ID, '+', Documents/Document/Language)
                          )
                           [1]
                      )
           ]
   "/>
    </Root>
  </xsl:template>

  <xsl:template match="Document">
    <Document>
      <xsl:apply-templates select=
    "key('DocumentsAndLanguage', ../../ID)
        [generate-id()
        =
         generate-id(key('DocumentsAndLanguageValue',
                         concat(../../ID, '+', Langauge)
                         )
                          [1]
                     )
         ]
    "/>
    </Document>
  </xsl:template>
</xsl:stylesheet>

先谢谢。

P.S。:不用说,我在XSLT 1.0中这样做

1 个答案:

答案 0 :(得分:1)

如果您在一个Document中将Query个元素与相同的语言组合在一起,那么您可能只需要一个键

<xsl:key name="Document" match="Document" use="concat(../../ID, '+', Language)"/>

然后你会得到不同的Document元素:

<xsl:template match="Document[generate-id() = generate-id(key('Document', concat(../../ID, '+', Language))[1])]">

然后,对于Document的每个子节点,您可以使用键来输出子节点以查找第一个空节点

    <xsl:for-each select="*">
        <xsl:copy>
            <xsl:value-of select="$current-group/*[name() = name(current())][normalize-space()][1]" />
        </xsl:copy>
    </xsl:for-each>

(其中current-group是设置为当前键值的变量。)

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:key name="Document" match="Document" use="concat(../../ID, '+', Language)"/>

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

  <xsl:template match="Document[generate-id() = generate-id(key('Document', concat(../../ID, '+', Language))[1])]">
    <Document>
        <xsl:variable name="current-group" select="key('Document', concat(../../ID, '+', Language))" />
        <xsl:for-each select="*">
            <xsl:copy>
                <xsl:value-of select="$current-group/*[name() = name(current())][normalize-space()][1]" />
            </xsl:copy>
        </xsl:for-each>
    </Document>
  </xsl:template>

  <xsl:template match="Document"/>
</xsl:stylesheet>