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

时间:2015-03-30 21:04:32

标签: xml xslt filemaker

我有一些从Filemaker导出的非常粗糙的XML。 几乎回答了我的问题(XSLT question. How to pair field tags with data when original XML has them in separate sections?)。该帖子中的xslt样式表优雅地使用<meta>字段中键入的名称重命名丑陋的原始xml。

这很棒,除非你看下面,否则你会看到每一行都有多个应该命名为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>

2 个答案:

答案 0 :(得分:1)

或者简单地说:

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

将返回:

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

答案 1 :(得分:0)

所以它听起来就像你想要三个batchID个,有<DATA>个值,batchPartnerIDbatchPartnerName一样。是吗?

如果有,您可以使用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>