【问题标题】:XSLT Change XML elements orderXSLT 更改 XML 元素顺序
【发布时间】:2014-04-10 13:54:56
【问题描述】:

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

  1. 新的元素顺序。查看源输出和所需输出之间的区别:<gmd:role> 应该出现在 <contactInfo> 之后,<CI_Contact> 中的元素也必须以不同的顺序出现。
  2. 将源中不存在的元素作为空元素添加到输出中 否则按原样复制元素(查看<address> 元素)

源文件

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

【问题讨论】:

    标签: xml xslt


    【解决方案1】:

    我想你想使用&lt;xsl:template match="gmd:CI_contact"&gt;,而不是&lt;xsl:template match="gmd:contactInfo"&gt;

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

    作为一个好习惯:在基于标识模板的样式表中,首选&lt;xsl:apply-templates&gt; 而不是&lt;xsl:copy&gt;

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

    假设:假设您想在任何地方删除所有 @foo 属性。因为上面使用了&lt;xsl:apply-templates select="@*"&gt;,所以是追加的问题

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

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

    【讨论】:

    • &lt;gmd:contactInfo&gt; 是一个错字!对不起,我的错!无论如何,我会改用&lt;gmd:CI_ResponsibleParty&gt;,因为我需要重新排列&lt;gmd:CI_Contact&gt; 子元素(就像你做的那样),还有应该出现在&lt;gmd:contactInfo&gt; 之后而不是之前出现在我的源文件中的&lt;gmd:role&gt;。所以... 1) 我可以仅使用一个模板执行此操作,还是需要为&lt;gmd:role&gt; 案例创建一个新模板? 2) 我是否需要为我想单独处理的那些元素创建像&lt;xsl:template match="gmd:CI_Contact" /&gt; 这样的“空”模板?
    • 1) 如果需要对CI_ResponsibleParty 的孩子重新排序,请为其编写模板。在其中使用几个&lt;xsl:apply-templates&gt;,就像在上面的代码中一样。 2) only 为您想要完全删除的内容创建空模板。 -- 请记住,您正在这里创建案例处理程序。 &lt;xsl:template match="gmd:CI_Contact" /&gt; 读作 “如果是 &lt;gmd:CI_Contact&gt;,则不产生输出并继续前进”,这不是你想要的。
    • 好的!因此,如果我需要从 &lt;MD_Metadata&gt; 根元素开始重新排序一些元素,我必须为它编写一个模板,其中只有 &lt;xsl:apply-templates select="@*" /&gt; 和一些 &lt;xsl:apply-templates select="gmd:MyNode" /&gt; 用于我想要更改位置的每个子元素。 ..对吗?
    • 这就是它的精髓。 :)
    • 我的命名空间转换面临一些新问题。如果你有时间... :-) link
    猜你喜欢
    • 2011-09-21
    • 1970-01-01
    • 1970-01-01
    • 2021-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多