XSLT为元素最佳实践添加名称空间前缀

时间:2014-04-17 08:33:00

标签: xml xslt namespaces prefix

出于验证目的,我需要将命名空间前缀添加到转换结果文件的每个元素。 我在下面写了转换,但我认为这不是做我想做的最好的方法,无论如何它不能100%工作......

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

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

我的改造有效但是:

  1. 在我的其余转换中,我需要操作一些元素来更改子元素的顺序,名称等......以及那些与另一个模板匹配的元素,似乎与身份模板不匹配< / strong>,所以我得到它们没有前缀。
  2. 我想知道如何改进我的代码
  3. 源文件

    <?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>

    的结果

1 个答案:

答案 0 :(得分:2)

我会写

<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>