XSLT将命名空间前缀添加到元素最佳实践



出于验证目的,我需要为转换结果文件的每个元素添加命名空间前缀。我在下面写了转换,但我认为这不是做我想做的事情的最佳方式,而且无论如何,它不是100%有效的。。。

在我的源文件中,有元素没有前缀,我需要添加默认名称空间的前缀gmd。但是,还有一些其他的元素已经指定了前缀,因为它们引用了其他名称空间,如gcogml,并且必须维护这些名称空间。

此外,在极少数情况下,我的输入文件可能已经设置了所有命名空间前缀。因此,我只想继续进行其余的转换(为了简单起见,我在这里只包含了另一个模板),而不添加任何内容。

我的转变奏效了,但是:

  1. 在我的转换的其余部分中,我需要操作一些元素来更改子元素的顺序、名称等……而那些与另一个模板匹配的元素,似乎与标识模板不匹配,所以我得到了不带前缀的元素
  2. 我想知道如何改进我的代码

源文件

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="c:ISO19139_rve.xsl"?>
<MD_Metadata xmlns="http://www.isotc211.org/schemas/2005/gmd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gco="http://www.isotc211.org/schemas/2005/gco" xmlns:gml="http://www.opengis.net/gml" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.isotc211.org/schemas/2005/gmd/gmd.xsd">
  <fileIdentifier>
    <gco:CharacterString>b0101011_Vincolo</gco:CharacterString>
  </fileIdentifier>
  <language>
    <gco:CharacterString>IT</gco:CharacterString>
  </language>
  <contact>
    <CI_ResponsibleParty>
      <organizationName>
        <gco:CharacterString>Comune di Conselve (capofila PATI)</gco:CharacterString>
      </organizationName>
      <role>
        <CI_RoleCode codeList="./resource/codeList.xml#CI_RoleCode" codeListValue="Autore">Autore</CI_RoleCode>
      </role>
      <contactInfo>
        <CI_Contact>
          <onlineResource>
            <CI_OnlineResource>
              <linkage>
                <URL>http://www.comune.conselve.it</URL>
              </linkage>
            </CI_OnlineResource>
          </onlineResource>
          <phone>
            <CI_Telephone>
              <voice>
                <gco:CharacterString>0499596511</gco:CharacterString>
              </voice>
            </CI_Telephone>
          </phone>
        </CI_Contact>
      </contactInfo>
      <temporalElement>
        <EX_TemporalExtent>
          <extent>
            <gml:TimePeriod gml:id="tp1">
              <gml:begin>
                <gml:TimeIstant gml:id="ti1">
                  <gml:timePosition>2007-12-01</gml:timePosition>
                </gml:TimeIstant>
              </gml:begin>
              <gml:end>
                <gml:TimeIstant gml:id="ti2">
                  <gml:timePosition>2010-01-01</gml:timePosition>
                </gml:TimeIstant>
              </gml:end>
            </gml:TimePeriod>
          </extent>
        </EX_TemporalExtent>
      </temporalElement>
    </CI_ResponsibleParty>
  </contact>
</MD_Metadata>

XSL转换:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    version="2.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:gml="http://www.opengis.net/gml"
    xmlns:gco="http://www.isotc211.org/schemas/2005/gco"
    xmlns:gmd="http://www.isotc211.org/schemas/2005/gmd"
    >
    <xsl:output indent="yes" encoding="UTF-8"/>
    <xsl:strip-space elements="*"/>
    <!-- default: identity template -->
    <xsl:template match="node() | @*">
        <xsl:choose>
            <xsl:when test="namespace-uri() eq 'http://www.isotc211.org/schemas/2005/gmd'">
                <xsl:element name="gmd:{name()}" namespace="http://www.isotc211.org/schemas/2005/gmd">
                    <xsl:copy-of select="namespace::*"/>
                    <xsl:apply-templates select="node() | @*"/>
                </xsl:element>    
            </xsl:when>
            <xsl:otherwise>
                <xsl:copy>
                    <xsl:apply-templates select="node() | @*" />
                </xsl:copy>
            </xsl:otherwise>            
        </xsl:choose>
    </xsl:template>
    <!-- override: <CI_Contact>, reorder -->
    <xsl:template match="gmd:CI_Contact">
        <xsl:copy>
            <xsl:apply-templates select="@*" />
            <xsl:apply-templates select="gmd:phone" />
            <xsl:apply-templates select="gmd:address" />
            <xsl:if test="not(gmd:address)">
                <gmd:address>
                    <gmd:CI_Address>
                        <gmd:electronicMailAddress>
                            <gco:CharacterString/>
                        </gmd:electronicMailAddress>
                    </gmd:CI_Address>
                </gmd:address>
            </xsl:if>
            <xsl:copy-of select="gmd:onlineResource" />
        </xsl:copy>
    </xsl:template>
</xsl:stylesheet>

我的实际结果

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="c:ISO19139_rve.xsl"?>
<gmd:MD_Metadata xmlns="http://www.isotc211.org/schemas/2005/gmd"
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:gco="http://www.isotc211.org/schemas/2005/gco"
                 xmlns:gml="http://www.opengis.net/gml"
                 xmlns:xlink="http://www.w3.org/1999/xlink"
                 xmlns:gmd="http://www.isotc211.org/schemas/2005/gmd"
                 xsi:schemaLocation="http://www.isotc211.org/schemas/2005/gmd/gmd.xsd">
   <gmd:fileIdentifier>
      <gco:CharacterString>b0101011_Vincolo</gco:CharacterString>
   </gmd:fileIdentifier>
   <gmd:language>
      <gco:CharacterString>IT</gco:CharacterString>
   </gmd:language>
   <gmd:contact>
      <gmd:CI_ResponsibleParty>
         <gmd:organizationName>
            <gco:CharacterString>Comune di Conselve (capofila PATI)</gco:CharacterString>
         </gmd:organizationName>
         <gmd:role>
            <gmd:CI_RoleCode codeList="./resource/codeList.xml#CI_RoleCode" codeListValue="Autore">Autore</gmd:CI_RoleCode>
         </gmd:role>
         <gmd:contactInfo>
            <CI_Contact>
               <gmd:phone>
                  <gmd:CI_Telephone>
                     <gmd:voice>
                        <gco:CharacterString>0499596511</gco:CharacterString>
                     </gmd:voice>
                  </gmd:CI_Telephone>
               </gmd:phone>
               <gmd:address>
                  <gmd:CI_Address>
                     <gmd:electronicMailAddress>
                        <gco:CharacterString/>
                     </gmd:electronicMailAddress>
                  </gmd:CI_Address>
               </gmd:address>
               <onlineResource>
                  <CI_OnlineResource>
                     <linkage>
                        <URL>http://www.comune.conselve.it</URL>
                     </linkage>
                  </CI_OnlineResource>
               </onlineResource>
            </CI_Contact>
         </gmd:contactInfo>
         <gmd:temporalElement>
            <gmd:EX_TemporalExtent>
               <gmd:extent>
                  <gml:TimePeriod gml:id="tp1">
                     <gml:begin>
                        <gml:TimeIstant gml:id="ti1">
                           <gml:timePosition>2007-12-01</gml:timePosition>
                        </gml:TimeIstant>
                     </gml:begin>
                     <gml:end>
                        <gml:TimeIstant gml:id="ti2">
                           <gml:timePosition>2010-01-01</gml:timePosition>
                        </gml:TimeIstant>
                     </gml:end>
                  </gml:TimePeriod>
               </gmd:extent>
            </gmd:EX_TemporalExtent>
         </gmd:temporalElement>
      </gmd:CI_ResponsibleParty>
   </gmd:contact>
</gmd:MD_Metadata>

正如您所看到的,转换只适用于其他模板不匹配的元素。查看<CI_Contact><onlineResource><CI_OnlineResource>等的结果。

我会写

<xsl:template match="node() | @*">
    <xsl:choose>
        <xsl:when test="namespace-uri() eq 'http://www.isotc211.org/schemas/2005/gmd'">
            <xsl:element name="gmd:{name()}" namespace="http://www.isotc211.org/schemas/2005/gmd">
                <xsl:copy-of select="namespace::*"/>
                <xsl:apply-templates select="node() | @*"/>
            </xsl:element>    
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy>
                <xsl:apply-templates select="node() | @*" />
            </xsl:copy>
        </xsl:otherwise>            
    </xsl:choose>
</xsl:template>

作为两个模板

<xsl:template match="node() | @*">
            <xsl:copy>
                <xsl:apply-templates select="node() | @*" />
            </xsl:copy>
</xsl:template>
<xsl:template match="gmd:*">
    <xsl:element name="gmd:{local-name()}" namespace="http://www.isotc211.org/schemas/2005/gmd">
                <xsl:copy-of select="namespace::*"/>
                <xsl:apply-templates select="node() | @*"/>
     </xsl:element>    
</xsl:template>

但当然,如果您有其他模板来匹配和转换http://www.isotc211.org/schemas/2005/gmd命名空间中的元素,那么您需要确保前缀更改也在其中完成,例如

<!-- override: <CI_Contact>, reorder -->
<xsl:template match="gmd:CI_Contact">
    <xsl:element name="gmd:{local-name()}" namespace="http://www.isotc211.org/schemas/2005/gmd">
        <xsl:apply-templates select="@*" />
        <xsl:apply-templates select="gmd:phone" />
        <xsl:apply-templates select="gmd:address" />
        <xsl:if test="not(gmd:address)">
            <gmd:address>
                <gmd:CI_Address>
                    <gmd:electronicMailAddress>
                        <gco:CharacterString/>
                    </gmd:electronicMailAddress>
                </gmd:CI_Address>
            </gmd:address>
        </xsl:if>
        <xsl:copy-of select="gmd:onlineResource" />
    </xsl:element>
</xsl:template>

最新更新