XSLT 样式表删除子项而不是重命名它们

XSLT stylesheet drops children instead of renaming them

我有一些从 Filemaker 导出的相当粗糙的 XML。有一个很棒的 post almost 回答了我的问题 (XSLT question. How to pair field tags with data when original XML has them in separate sections?)。 post 中的 xslt 样式表优雅地重命名了丑陋的原始 xml,并在 <meta> 字段中键入了名称。

太好了,除非您看下面,您会看到每一行都有多个元素,它们应该命名为 batchIDbatchPartnerIDbatchPartnerName但是,这三个元素中只有第一个子元素被重命名 - 其余的都被简单地删除了。

我想样式表只是没有遍历元素(xml 它最初工作的每个 <COL> 只有一个子元素。不幸的是,我对 XSLT 不够熟悉解决这个问题...帮不上什么忙?谢谢。

原文XML:

<?xml version="1.0" encoding="UTF-8"?>
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
  <ERRORCODE>0</ERRORCODE>
  <PRODUCT BUILD="11-13-2014" NAME="FileMaker" VERSION="Pro 13.0v4"/>
  <DATABASE DATEFORMAT="M/d/yyyy" LAYOUT="" NAME="ArticleIndex.fmp12" RECORDS="3678" TIMEFORMAT="h:mm:ss a"/>
  <METADATA>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="id" TYPE="NUMBER"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="author" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="url" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="brand" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="publishDate" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="categoryAll" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="originalTitle" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="originalBody" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="standardTitle" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="standardSubtitle" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="standardPublishDate" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="standardBody" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="standardNotes" TYPE="TEXT"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="standardLastUpdated" TYPE="DATE"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="standardLastReviewed" TYPE="DATE"/>
    <FIELD EMPTYOK="NO" MAXREPEAT="1" NAME="batchID" TYPE="NUMBER"/>
    <FIELD EMPTYOK="NO" MAXREPEAT="1" NAME="batchPartnerID" TYPE="NUMBER"/>
    <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="batchPartnerName" TYPE="TEXT"/>
  </METADATA>
  <RESULTSET FOUND="12">
    <ROW MODID="24" RECORDID="2028">
      <COL>
        <DATA>11023</DATA>
      </COL>
      <COL>
        <DATA>Tom Myer</DATA>
      </COL>
      <COL>
        <DATA>http://www.sitepoint.com/really-good-introduction-xml/</DATA>
      </COL>
      <COL>
        <DATA>SitePoint</DATA>
      </COL>
      <COL>
        <DATA>August 2005</DATA>
      </COL>
      <COL>
        <DATA/>
      </COL>
      <COL>
        <DATA>A Really Good Introduction to XML</DATA>
      </COL>
      <COL>
        <DATA>A Really Good Introduction to XML —E. Berliet, Lyon, France

In this chapter, we’ll cover the basics of XML – essentially, most of the information you’ll need to know to get a handle on this exciting technology. After we’re done exploring some terminology and examples, we’ll jump right in and start working with XML documents. Then, we’ll spend some time starting the project we’ll develop through the course of this book: building an XML-powered content management system.

This excerpt is taken from No Nonsense XML Web Development with PHP, SitePoint’s new release, by Thomas Myer, which was designed to help you start using XML to build intelligent ‘Future-Proof’ PHP applications today.</DATA>
      </COL>
      <COL>
        <DATA>A Really, Really, Really Good Introduction to XML</DATA>
      </COL>
      <COL>
        <DATA>Starting out right</DATA>
      </COL>
      <COL>
        <DATA>8/24/2005</DATA>
      </COL>
      <COL>
        <DATA>A Really, Really, Really Good Introduction to XML —E. Berliet, Lyon, France

In this chapter, we’ll cover the basics of XML – essentially, most of the information you’ll need to know to get a handle on this exciting technology. After we’re done exploring some terminology and examples, we’ll jump right in and start working with XML documents. Then, we’ll spend some time starting the project we’ll develop through the course of this book: building an XML-powered content management system.

This excerpt is taken from No Nonsense XML Web Development with PHP, SitePoint’s new release, by Thomas Myer, which was designed to help you start using XML to build intelligent ‘Future-Proof’ PHP applications today.

The title contains over 350 pages of XML and PHP goodies. It walks you through the process of building a fully-functional XML-based content management system with PHP. And all the code used in the book is available to customers in a downloadalbe archive.

To find out more about “No Nonsense XML Web Development with PHP”, visit the book’s information page, or review the contents of the entire publication. As always, you can download this excerpt as a PDF if you prefer.
     </COL>
      <COL>
        <DATA/>
      </COL>
      <COL>
        <DATA/>
      </COL>
      <COL>
        <DATA/>
      </COL>
      <COL>
        <DATA>4127</DATA>
        <DATA>4130</DATA>
        <DATA>4136</DATA>
      </COL>
      <COL>
        <DATA>1101</DATA>
        <DATA>1107</DATA>
        <DATA>1140</DATA>
      </COL>
      <COL>
        <DATA>First Client Name</DATA>
        <DATA>Second Client Name</DATA>
        <DATA>Third Client Name</DATA>
      </COL>
    </ROW>
  </RESULTSET>
</FMPXMLRESULT>

XSLT 样式表:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:fmp="http://www.filemaker.com/fmpxmlresult"
  exclude-result-prefixes="fmp"
>
<xsl:output method="xml" encoding="UTF-8" indent="yes"/>

  <!-- the key indexes the METADATA fields by their position -->
  <xsl:key 
    name="kMetaData" 
    match="fmp:METADATA/fmp:FIELD" 
    use="count(preceding-sibling::fmp:FIELD) + 1" 
  />

  <!-- separate templates increase readability -->
  <xsl:template match="/fmp:FMPXMLRESULT">
    <content>
      <xsl:apply-templates select="fmp:RESULTSET/fmp:ROW" />
    </content>
  </xsl:template>

  <xsl:template match="fmp:ROW">
    <contentitem>
      <xsl:apply-templates select="fmp:COL" />
    </contentitem>
  </xsl:template>

  <xsl:template match="fmp:COL">
    <!-- column name lookup is high-speed because of the key -->
    <xsl:element name="{string(key('kMetaData', position())/@NAME)}">
      <xsl:value-of select="fmp:DATA" />
    </xsl:element>
  </xsl:template>

</xsl:stylesheet>

已翻译 XML:

<?xml version="1.0" encoding="UTF-8"?>
<content>
  <contentitem>
    <id>11023</id>
    <author>Tom Myer</author>
    <url>http://www.sitepoint.com/really-good-introduction-xml/</url>
    <brand>SitePoint</brand>
    <publishDate>August 2005</publishDate>
    <categoryAll/>
    <originalTitle>A Really Good Introduction to XML</originalTitle>
    <originalBody>A Really Good Introduction to XML —E. Berliet, Lyon, France

In this chapter, we’ll cover the basics of XML – essentially, most of the information you’ll need to know to get a handle on this exciting technology. After we’re done exploring some terminology and examples, we’ll jump right in and start working with XML documents. Then, we’ll spend some time starting the project we’ll develop through the course of this book: building an XML-powered content management system.

This excerpt is taken from No Nonsense XML Web Development with PHP, SitePoint’s new release, by Thomas Myer, which was designed to help you start using XML to build intelligent ‘Future-Proof’ PHP applications today.</originalBody>
    <standardTitle>A Really, Really, Really Good Introduction to XML</standardTitle>
    <standardSubtitle>Starting out right</standardSubtitle>
    <standardPublishDate>8/24/2005</standardPublishDate>
    <standardBody>A Really, Really, Really Good Introduction to XML —E. Berliet, Lyon, France

In this chapter, we’ll cover the basics of XML – essentially, most of the information you’ll need to know to get a handle on this exciting technology. After we’re done exploring some terminology and examples, we’ll jump right in and start working with XML documents. Then, we’ll spend some time starting the project we’ll develop through the course of this book: building an XML-powered content management system.

This excerpt is taken from No Nonsense XML Web Development with PHP, SitePoint’s new release, by Thomas Myer, which was designed to help you start using XML to build intelligent ‘Future-Proof’ PHP applications today.

The title contains over 350 pages of XML and PHP goodies. It walks you through the process of building a fully-functional XML-based content management system with PHP. And all the code used in the book is available to customers in a downloadalbe archive.

To find out more about “No Nonsense XML Web Development with PHP”, visit the book’s information page, or review the contents of the entire publication. As always, you can download this excerpt as a PDF if you prefer.</standardBody>
    <standardNotes/>
    <standardLastUpdated/>
    <standardLastReviewed/>
    <batchID>4127</batchID>
    <batchPartnerID>1101</batchPartnerID>
    <batchPartnerName>First Client Name</batchPartnerName>
  </contentitem>
</content>

所以它 听起来 就像你想要三个 batchID 具有三个 <DATA> 值,batchPartnerID 和 [=15 一样=].是吗?

如果是这样,您可以使用 for-each 遍历 <DATA>

<xsl:template match="fmp:COL">
  <xsl:variable name="elName"
                select="key('kMetaData', position())/@NAME" />
  <xsl:for-each select="fmp:DATA">
    <xsl:element name="{$elName}">
      <xsl:value-of select="." />
    </xsl:element>
  </xsl:for-each>
</xsl:template>

或者您可以使用参数化模板:

<xsl:template match="fmp:COL">
  <xsl:apply-templates select="fmp:DATA">
    <xsl:with-param name="elName" select="key('kMetaData', position())/@NAME" />
  </xsl:apply-templates>
</xsl:template>

<xsl:template match="fmp:DATA">
  <xsl:param name="elName" select="name()" />

  <xsl:element name="{$elName}">
    <xsl:value-of select="." />
  </xsl:element>
</xsl:template>

或者简单地说:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fmp="http://www.filemaker.com/fmpxmlresult"
exclude-result-prefixes="fmp">
<xsl:output method="xml" version="1.0" encoding="utf-8" indent="yes"/>

<xsl:key name="kMetaData" match="fmp:METADATA/fmp:FIELD" use="count(preceding-sibling::fmp:FIELD) + 1" />

<!-- separate templates are not required for something as simple as this -->
<xsl:template match="/">
    <content>
        <xsl:for-each select="fmp:FMPXMLRESULT/fmp:RESULTSET/fmp:ROW">
            <contentitem>
                <xsl:for-each select="fmp:COL">
                    <xsl:variable name="field-name" select="key('kMetaData', position())/@NAME" />
                    <xsl:for-each select="fmp:DATA">
                        <xsl:element name="{$field-name}">
                            <xsl:value-of select="." />
                        </xsl:element>
                    </xsl:for-each>
                </xsl:for-each>
            </contentitem>
        </xsl:for-each>
    </content>
</xsl:template>

</xsl:stylesheet>

请注意,这是假设您的字段名称(并且始终是)也是有效的 XML 元素名称。如果您不能确定这一点,则在导出时切换到 FMPDSORESULT 语法。这会将您的字段名称转换为有效的 XML 名称(例如,将空格替换为下划线)- 但您还需要不同的 XSLT 样式表。


编辑:

例如,将以下 FMPDSORESULT 导出作为输入:

XML

<FMPDSORESULT xmlns="http://www.filemaker.com/fmpdsoresult">
<ERRORCODE>0</ERRORCODE>
<DATABASE>example.fmp12</DATABASE>
<LAYOUT/>
<ROW MODID="1" RECORDID="1">
<some_field>Alpha</some_field>
<another_field>
<DATA>101</DATA>
<DATA>102</DATA>
<DATA>103</DATA>
</another_field>
</ROW>
<ROW MODID="2" RECORDID="2">
<some_field>Bravo</some_field>
<another_field>
<DATA>21</DATA>
<DATA>22</DATA>
</another_field>
</ROW>
</FMPDSORESULT>

以下样式表:

XSLT 1.0

<xsl:stylesheet version='1.0'       
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
xmlns:fmp="http://www.filemaker.com/fmpdsoresult"
exclude-result-prefixes="fmp">
<xsl:output version="1.0" encoding="UTF-8" method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:template match="/">
    <root>
        <xsl:for-each select="fmp:FMPDSORESULT/fmp:ROW">
            <row> 
                <xsl:apply-templates/>
            </row>
        </xsl:for-each>
    </root>
</xsl:template>

<xsl:template match="fmp:ROW/*[not(fmp:DATA)]">
    <xsl:element name="{name(.)}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

<xsl:template match="fmp:DATA">
    <xsl:element name="{name(..)}">
        <xsl:value-of select="."/>
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

将 return:

<?xml version="1.0" encoding="UTF-8"?>
<root>
  <row>
    <some_field>Alpha</some_field>
    <another_field>101</another_field>
    <another_field>102</another_field>
    <another_field>103</another_field>
  </row>
  <row>
    <some_field>Bravo</some_field>
    <another_field>21</another_field>
    <another_field>22</another_field>
  </row>
</root>