XSLT更改XML元素顺序

时间:2014-04-10 13:54:57

标签: xml xslt

我需要使用转换重新排列源XML文件以获取:

  1. 新的元素订单。查看源和期望输出之间的差异:<gmd:role>应显示在<contactInfo>之后,<CI_Contact>内的元素也必须以不同的顺序显示。
  2. 将源中不存在的元素添加为输出中的空元素,否则按原样复制元素(查看<address>元素)
  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">
    <CI_ResponsibleParty>
        <organizationName>
            <gco:CharacterString>Organisation Name</gco:CharacterString>
        </organizationName>
        <role>
            <CI_RoleCode codeList="./resource/codeList.xml#CI_RoleCode" codeListValue="Proprietario">Proprietario</CI_RoleCode>
        </role>
        <contactInfo>
            <CI_Contact>
                <onlineResource>
                    <CI_OnlineResource>
                        <linkage>
                            <URL>http://www.mydomain.it</URL>
                        </linkage>
                    </CI_OnlineResource>
                </onlineResource>
                <phone>
                    <CI_Telephone>
                        <voice>
                            <gco:CharacterString>+39 123 456789</gco:CharacterString>
                        </voice>
                    </CI_Telephone>
                </phone>
            </CI_Contact>
        </contactInfo>
    </CI_ResponsibleParty>
    </MD_Metadata>
    

    期望的结果

    <?xml version="1.0" encoding="UTF-8"?>
    <?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">
    <gmd:CI_ResponsibleParty>
      <gmd:organisationName>
        <gco:CharacterString>Organisation Name</gco:CharacterString>
      </gmd:organisationName>
      <gmd:contactInfo>
        <gmd:CI_Contact>
          <gmd:phone>
            <gmd:CI_Telephone>
              <gmd:voice>
                <gco:CharacterString>+39 123 456789</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>
          <gmd:onlineResource>
            <gmd:CI_OnlineResource>
              <gmd:linkage>
                <gmd:URL>http://www.mydomain.it</gmd:URL>
              </gmd:linkage>
            </gmd:CI_OnlineResource>
          </gmd:onlineResource>
        </gmd:CI_Contact>
      </gmd:contactInfo>
      <gmd:role>
        <gmd:CI_RoleCode codeList="./resource/codeList.xml#CI_RoleCode" codeListValue="owner">Proprietario</gmd:CI_RoleCode>
      </gmd:role>
    </gmd:CI_ResponsibleParty>
    </MD_Metadata>
    

    我的转型

    <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/3.2"
        xmlns:gco="http://www.isotc211.org/schemas/2005/gco"
        xmlns:gmd="http://www.isotc211.org/schemas/2005/gmd"
        xmlns="http://www.isotc211.org/schemas/2005/gmd"
        >
    
        <xsl:strip-space elements="*"/>
    
        <xsl:output indent="yes" encoding="UTF-8"/>
    
        <!-- identity template -->
        <xsl:template match="node() | @*">
            <xsl:copy>
                <xsl:apply-templates select="node() | @*" />
            </xsl:copy>
        </xsl:template>
    
        <xsl:template match="gmd:CI_ResponsibleParty" exclude-result-prefixes="#all">
            <xsl:copy>
                <!--<xsl:copy-of select="@*" />-->
                <xsl:copy-of select="gmd:organizationName" />
                <xsl:apply-templates select="gmd:contactInfo" />
                <xsl:copy-of select="gmd:role" />
                <!--<xsl:apply-templates select="node()" />-->
            </xsl:copy>
        </xsl:template>
    
        <!--<xsl:template match="gmd:contactInfo" />-->
    
        <xsl:template match="gmd:contactInfo" exclude-result-prefixes="#all">
            <xsl:copy>
                <xsl:copy-of select="gmd:phone" />
                <xsl:apply-templates select="gmd:address" />
                <xsl:if test="not(gmd:address)">
                    <address>
                        <CI_Address>
                            <electronicMailAddress>
                                <gco:CharacterString/>
                            </electronicMailAddress>
                        </CI_Address>
                    </address>
                </xsl:if>
                <xsl:copy-of select="gmd:onlineResource" />
            </xsl:copy>
        </xsl:template>
    </xsl:stylesheet>
    

1 个答案:

答案 0 :(得分:2)

我认为您要使用<xsl:template match="gmd:CI_contact">,而不是<xsl:template match="gmd:contactInfo">

<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)">
            <address>
                <CI_Address>
                    <electronicMailAddress>
                        <gco:CharacterString/>
                    </electronicMailAddress>
                </CI_Address>
            </address>
        </xsl:if>
        <xsl:apply-templates select="gmd:onlineResource" />
    </xsl:copy>
</xsl:template>

作为一种良好做法:在基于身份模板的样式表中,首选<xsl:apply-templates>而不是<xsl:copy>

最终效果将是相同的(输入将被复制),但这样您可以轻松附加另一个处理特殊情况的模板,而无需触及现有模板。

假设:假设您想要删除所有@foo属性。由于上述内容使用<xsl:apply-templates select="@*">,因此需要附加

<xsl:template match="@foo" />

但是,如果您使用<xsl:copy-of select="@*" />,则必须更改此行以及可能会复制@foo的其他十几个地方。