结合这两个XSLT模板

时间:2018-11-02 18:18:29

标签: xml xslt xslt-1.0

在使用XSLT 1.0(必须为1.0)转换XML时遇到一些麻烦。 我有这个XML示例:

<feed xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xml:base="http://servico.dados.gov.pt/v1/dgpj/">
  <!--  Crimes registados 2014-1993 por localização  -->
  <title type="text">Crimesregistados20141993porlocalizacao</title>
  <entry>
    <content>
      <m:properties>
        <d:RowKey>635951168253516361</d:RowKey>
        <d:distritoinfracao>Aveiro</d:distritoinfracao>
        <d:municipioinfracao>Agueda</d:municipioinfracao>
        <d:a2014ncrimes>1392</d:a2014ncrimes>
        <d:a2013ncrimes>1657</d:a2013ncrimes>
      </m:properties>
    </content>
    <content>
      <m:properties>
        <d:RowKey>635951168253516361</d:RowKey>
        <d:distritoinfracao>Algarve</d:distritoinfracao>
        <d:municipioinfracao>Faro</d:municipioinfracao>
        <d:a2014ncrimes>1300</d:a2014ncrimes>
        <d:a2013ncrimes>1600</d:a2013ncrimes>
      </m:properties>
    </content>
    <content>
      <m:properties>
        <d:RowKey>635950068253516361</d:RowKey>
        <d:distritoinfracao>Aveiro</d:distritoinfracao>
        <d:municipioinfracao>Ovar</d:municipioinfracao>
        <d:a2014ncrimes>1999</d:a2014ncrimes>
        <d:a2013ncrimes>1666</d:a2013ncrimes>
      </m:properties>
    </content>
  </entry>
</feed>

我有这个XSLT模板来删除名称空间,它可以工作:

<xsl:template match="*">
    <xsl:element name="{local-name()}">
      <xsl:for-each select="@*">
        <xsl:attribute name="{local-name()}">
          <xsl:value-of select="."/>
        </xsl:attribute>
      </xsl:for-each>
      <xsl:apply-templates/>
    </xsl:element>
  </xsl:template>

这个XSLT模板以我想要的方式重新排列我的XML,但是只有在我手动删除所有名称空间的情况下它才有效:

<xsl:key name="d" match="properties" use="distritoinfracao" />
 <xsl:template match="/*">
    <xsl:copy>
      <xsl:apply-templates select="entry/content" />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="entry/content">
      <xsl:apply-templates select="properties[generate-id(.) = generate-id(key('d',distritoinfracao)[1])]"/>
  </xsl:template>

  <xsl:template match="properties[generate-id(.) = generate-id(key('d',distritoinfracao)[1])]">
    <xsl:element name="{translate(distritoinfracao,' ','_')}">
      <xsl:for-each select="key('d',distritoinfracao)">
        <xsl:element name="{translate(municipioinfracao,' ','_')}">
          <xsl:copy-of select="a2014ncrimes" />
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>

我不能两者兼而有之。有什么建议么? 如果可以的话,是否有等效于XSLT 2.0的LXML(python)?

1 个答案:

答案 0 :(得分:0)

要合并两个XSLT文件,您不能避免在XSLT中包含名称空间。

在这个答案中,我只是将名称空间合并到第二个XSLT中,并用

替换了简单的xsl:copy
<xsl:element name="...">
  <xsl:value-of select="..." />
</xsl:element>

删除其名称空间。这样,您可以从元素中删除所有名称空间。必须对所有名称空间的元素分别进行此操作。

生成的XSLT-1.0为:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" 
xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata">
    <xsl:output method="xml" indent="yes"/>
    <xsl:key name="d" match="m:properties" use="d:distritoinfracao" />

 <xsl:template match="/*">
    <xsl:element name="{local-name()}">
      <xsl:apply-templates select="entry/content" />
    </xsl:element>
  </xsl:template>

  <xsl:template match="entry/content">
      <xsl:apply-templates select="m:properties[generate-id(.) = generate-id(key('d',d:distritoinfracao)[1])]"/>
  </xsl:template>

  <xsl:template match="m:properties[generate-id(.) = generate-id(key('d',d:distritoinfracao)[1])]">
    <xsl:element name="{translate(d:distritoinfracao,' ','_')}">
      <xsl:for-each select="key('d',d:distritoinfracao)">
        <xsl:element name="{translate(d:municipioinfracao,' ','_')}">
            <xsl:element name="a2014ncrimes">
                <xsl:value-of select="d:a2014ncrimes" />
            </xsl:element>
        </xsl:element>
      </xsl:for-each>
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>

输出为:

<?xml version="1.0"?>
<feed>
    <Aveiro>
        <Agueda>
            <a2014ncrimes>1392</a2014ncrimes>
        </Agueda>
        <Ovar>
            <a2014ncrimes>1999</a2014ncrimes>
        </Ovar>
    </Aveiro>
    <Algarve>
        <Faro>
            <a2014ncrimes>1300</a2014ncrimes>
        </Faro>
    </Algarve>
</feed>