Имена полей XSLT от Filemaker Pro - PullRequest
       15

Имена полей XSLT от Filemaker Pro

0 голосов
/ 03 сентября 2018

Я новичок в XSLT и пытаюсь преобразовать файл XML, сгенерированный из Filemaker Pro, используя грамматику fmpxmlresult. Filemaker выводит RAW XML следующим образом:

<?xml version="1.0" encoding="UTF-8"?>
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
   <ERRORCODE>0</ERRORCODE>
   <PRODUCT BUILD="02-13-2018" NAME="FileMaker" VERSION="ProAdvanced 16.0.5" />
   <DATABASE DATEFORMAT="D/m/yyyy" LAYOUT="" NAME="fatture elettronica.fmp12" RECORDS="1" TIMEFORMAT="k:mm:ss " />
   <METADATA>
      <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="data" TYPE="DATE" />
      <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="ID" TYPE="TEXT" />
      <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="righe::descrizione" TYPE="TEXT" />
      <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="righe::prezzo" TYPE="TEXT" />
   </METADATA>
   <RESULTSET FOUND="1">
      <ROW MODID="1" RECORDID="1">
         <COL>
            <DATA>31/08/2018</DATA>
         </COL>
         <COL>
            <DATA>1</DATA>
         </COL>
         <COL>
            <DATA>patate</DATA>
            <DATA>pomodori</DATA>
            <DATA>uva</DATA>
         </COL>
         <COL>
            <DATA>100</DATA>
            <DATA>50</DATA>
            <DATA>70</DATA>
         </COL>
      </ROW>
   </RESULTSET>
</FMPXMLRESULT>

В моем XSLT я выбираю поля, используя

<xsl:value-of select="fmp:COL[1]/fmp:DATA"/>

Это работает, но это немного сбивает с толку, потому что у меня есть XML-файл с большим количеством полей, и я могу легко указать неправильное поле по номеру. Есть ли способ выбрать поле, используя имя поля, которое указано в разделе метаданных? Я пытался искать, но я не могу даже представить правильные ключевые слова для поиска. Спасибо

Ответы [ 3 ]

0 голосов
/ 03 сентября 2018

Вы можете определить ключ для хранения имен полей и извлечь имя из него, используя функцию подсчета.

Примерно так.

<!-- Define a key to get the first field and all fields that follow it by the field name -->
<xsl:key name="K" match="/fmp:FMPXMLRESULT/fmp:METADATA/fmp:FIELD" use="@NAME" />
<xsl:key name="K" match="/fmp:FMPXMLRESULT/fmp:METADATA/fmp:FIELD" use="following-sibling::fmp:FIELD/@NAME" />


<!-- Shortform to get a value for an attribute -->
<MyField  SomeAttr="{fmp:COL[count(key('K', 'SomeAttr'))]}"/>        

<!-- Format for getting a value for an element -->
<MyField>
    <xsl:value-of select="fmp:COL[count(key('K', 'MyField'))]/fmp:DATA" />
</MyField>    

Этот метод также имеет то преимущество, что если вы измените свой порядок экспорта полей в FileMaker, ваш XSLT будет продолжать работать. Если вы изменяете имя поля в FileMaker, вам просто нужно изменить один оператор в вашем XSLT, куда вы извлекаете это поле.

0 голосов
/ 04 сентября 2018

Я решил таким образом:

<xsl:variable name="mdf" select="/fmp:FMPXMLRESULT/fmp:METADATA/fmp:FIELD" /> <xsl:variable name="ID" select="count($mdf[following-sibling::fmp:FIELD/@NAME = 'ID']) + 1" />

тогда я вызываю переменную:

<xsl:value-of select="fmp:COL[$ID]/fmp:DATA"/>
0 голосов
/ 03 сентября 2018

В чистом XSLT / XPath 1 трудно найти компактное выражение, например, чтобы выбрать столбец, в котором соответствующий FIELD имеет значение атрибута NAME ID, вам потребуется сложный выбор, например <xsl:value-of select="fmp:COL[count($fields[@NAME = 'ID']/preceding-sibling::fmp:FIELD) + 1]/fmp:DATA"/> :

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

  <xsl:output method="html" indent="yes"/>

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

  <xsl:variable name="fields" select="//fmp:FIELD"/>

  <xsl:template match="fmp:ROW">
    <xsl:value-of select="fmp:COL[count($fields[@NAME = 'ID']/preceding-sibling::fmp:FIELD) + 1]/fmp:DATA"/>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty -development.net / 94hvTzA / 2

В XSLT 2 или 3 вы можете определить функцию, возвращающую индекс требуемого FIELD на основе значения атрибута NAME и иметь компактное выражение <xsl:value-of select="COL[mf:col-pos('ID')]/DATA"/>:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xpath-default-namespace="http://www.filemaker.com/fmpxmlresult"
    xmlns:mf="http://example.com/mf"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output method="html" indent="yes" html-version="5"/>

  <xsl:variable name="main-doc" select="/"/>

  <xsl:key name="field" match="FIELD" use="@NAME"/>

  <xsl:function name="mf:col-pos" as="xs:integer">
      <xsl:param name="field-name" as="xs:string"/>
      <xsl:sequence select="mf:col-pos($field-name, $main-doc)"/>
  </xsl:function>

  <xsl:function name="mf:col-pos" as="xs:integer">
      <xsl:param name="field-name" as="xs:string"/>
      <xsl:param name="field-anc" as="node()"/>
      <xsl:for-each select="key('field', $field-name, $field-anc)">
          <xsl:number/>
      </xsl:for-each>
  </xsl:function>

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

  <xsl:template match="ROW">
     <xsl:value-of select="COL[mf:col-pos('ID')]/DATA"/>
  </xsl:template>

</xsl:stylesheet>
...