XSLT问题.当原始XML位于单独的部分中时,如何将字段标记与数据配对? [英] XSLT question. How to pair field tags with data when original XML has them in separate sections?

查看:79
本文介绍了XSLT问题.当原始XML位于单独的部分中时,如何将字段标记与数据配对?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我希望我不会因为提及Filemaker而失去任何人.我试图将它的XML导出转换为SSIS可用的东西. FM的本机XML导出在同一XML文件的不同部分中具有字段名称和数据.这列出了我需要执行的操作,当前执行的操作以及底部的原始FM导出,以供参考.今天早上我还没有看过XML翻译,所以请忍受:D.我可以根据需要发布更多信息.

I hope I don't lose anyone by mentioning Filemaker. I am trying to turn it's XML export into something usable by SSIS. FM's native XML export has field names and data in separate sections of the same XML file. This lists what I need it to do, what I currently did, and the original FM export at the bottom for reference. I have not seen XML translations before this morning, so bear with me :D. I can post more info as necessary.

<!-- What we actually want example -->
<?xml version="1.0" encoding="UTF-8"?>

<PRODUCTRECS>
<PRODUCT>
    <name>Dr. Zim</name>
    <address>1234 Internet Way</address>
    <city/><state/><zip/>
</PRODUCT>
...
</PRODUCTRECS>

使用XSLt,有没有一种方法可以读取顶部的字段名称,并在转换时将字段名称放在实际数据周围?目前,我只是使用IF语句来选择位置(这样可以起作用,但是非常依赖和混乱):

Is there a way with XSLt to read the field names at the top and put the field names around the actual data when we translate it? Currently, I just pick out the position with IF statements like so (which works but is very dependent and messy):

<!-- Current nightmare code, check for each individually and print it out -->
<xsl:template match="fmp:FMPXMLRESULT">
<PRODUCTRECS>
<xsl:for-each select="fmp:RESULTSET/fmp:ROW">
    <PRODUCT>
<xsl:for-each select="fmp:COL">
<xsl:if test="position()=1">
    <name><xsl:value-of select="fmp:DATA"/></name>
</xsl:if>
...
</xsl:for-each>
    </PRODUCT>
</xsl:for-each>
</PRODUCTRECS>
</xsl:template>

这是Filemaker默认输出的内容:

This is what Filemaker outputs by default:

<?xml version="1.0" encoding="UTF-8" ?>
<FMPXMLRESULT xmlns="http://www.filemaker.com/fmpxmlresult">
<ERRORCODE>0</ERRORCODE>
<PRODUCT BUILD="01-01-2009" NAME="FileMaker Pro" VERSION="10.0v3"/>
<DATABASE DATEFORMAT="M/d/yyyy" LAYOUT="" NAME="filename.fp7" RECORDS="10" TIMEFORMAT="h:mm:ss a"/>
<METADATA>
  <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="name" TYPE="TEXT"/>
  <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="address" TYPE="TEXT"/>
  <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="city" TYPE="TEXT"/>
  <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="state" TYPE="TEXT"/>
  <FIELD EMPTYOK="YES" MAXREPEAT="1" NAME="zip" TYPE="TEXT"/>
</METADATA>
<RESULTSET FOUND="10">
<ROW MODID="0" RECORDID="1">
  <COL><DATA>Dr. Zim</DATA></COL>
  <COL><DATA>1234 Internet Way</DATA></COL>
  <COL><DATA></DATA></COL>
  <COL><DATA></DATA></COL>
  <COL><DATA></DATA></COL>
  ...
</ROW>
...
</RESULTSET>
</FMPXMLRESULT>

期待在那里的专家XSLTers. :)我遇到的另一个问题是,当原始格式以XML(Text)(00009.99000000)格式存储在XML中时,如何将数字价格格式化为9.99美元的货币,但是我可以处理这个价格.

Looking forward to the guru XSLTers out there. :) Another question I had was how to format a numeric price when the original is stored as Text (00009.99000000) in the XML in to a currency of $9.99, but I can work on this one.

推荐答案

解决此问题的一种优雅方法是:

One elegant way to solve this problem is this:

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

  <!-- 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">
    <PRODUCTRECS>
      <xsl:apply-templates select="fmp:RESULTSET/fmp:ROW" />
    </PRODUCTRECS>
  </xsl:template>

  <xsl:template match="fmp:ROW">
    <PRODUCT>
      <xsl:apply-templates select="fmp:COL" />
    </PRODUCT>
  </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>

我的系统上的哪个输出

<PRODUCTRECS>
  <PRODUCT>
    <name>Dr. Zim</name>
    <address>1234 Internet Way</address>
    <city></city>
    <state></state>
    <zip></zip>
  </PRODUCT>
</PRODUCTRECS>

但是,请注意,XML元素名称要比FileMaker列名称受更严格的规则约束.如果您的列名违反了这些规则,以上内容将崩溃并燃烧.

However, be warned that XML element names are subject to stricter rules than FileMaker column names. The above will crash and burn if your column names violate those rules.

样式表的显着特征是:

  • 一个<xsl:key>用于快速查找节点-对于较大的输入,这应该变得很明显
  • exclude-result-prefixes以防止在结果中声明fmp命名空间
  • <xsl:element>创建具有动态名称的元素
  • 使用preceding-sibling XPath轴作为确定节点位置的方式(因为position()函数在<xsl:key> s中不起作用
  • an <xsl:key> for speedy lookup of nodes - this should become noticeable for larger inputs
  • exclude-result-prefixes to prevent declaration of the fmp namespace in the result
  • <xsl:element> to create elements with a dynamic name
  • the use of the preceding-sibling XPath axis as a way of determining node position (because the position() function does not work in <xsl:key>s

继续,问是否有不清楚的地方.

Go ahead and ask if anything is unclear.

您的其他问题(数字格式)在这里有一个答案: XSL:格式化数字,排除尾随零.

Your other problem (number formatting) has an answer here: XSL: Formatting numbers, excluding trailing zeroes.

这篇关于XSLT问题.当原始XML位于单独的部分中时,如何将字段标记与数据配对?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆