通过xsl更改属性值

时间:2013-09-27 12:34:22

标签: xml xslt

我有以下xml文件:

<xc:XmlCache xmlns:xc="XmlCache" xmlns:mp="mx.MarketParameters" xmlns:fx="mx.MarketParameters.Forex" xmlns:fxsp="mx.MarketParameters.Forex.Spot">
 <xc:XmlCacheArea xc:value="MarketParameters">
  <mp:nickName xc:value="MDS" xmlns:mp="mx.MarketParameters">
   <mp:date xc:value="20130315">
    <fx:forex xmlns:fx="mx.MarketParameters.Forex">
     <fxsp:spot xmlns:fxsp="mx.MarketParameters.Forex.Spot">
      <fxsp:pair xc:value="AUD/AED" xc:type="Fields">
       <mp:ask xc:keyFormat="N">1.0000000</mp:ask> 
       <mp:bid xc:keyFormat="N">1.0000000</mp:bid> 
       <mp:formFactor xc:keyFormat="N">1</mp:formFactor> 
       <mp:high xc:keyFormat="N">0.0000000</mp:high> 
       <mp:low xc:keyFormat="N">0.0000000</mp:low> 
       <mp:mid xc:keyFormat="N">1.0000000</mp:mid> 
       <mp:quotation xc:keyFormat="C">AUD-AED</mp:quotation> 
      </fxsp:pair>
      <fxsp:pair xc:value="BHD/AED" xc:type="Fields">
       <mp:ask xc:keyFormat="N">0.8264463</mp:ask> 
       <mp:bid xc:keyFormat="N">0.8264463</mp:bid> 
       <mp:formFactor xc:keyFormat="N">1</mp:formFactor> 
       <mp:high xc:keyFormat="N">0.0000000</mp:high> 
       <mp:low xc:keyFormat="N">0.0000000</mp:low> 
       <mp:mid xc:keyFormat="N">0.8264463</mp:mid> 
       <mp:quotation xc:keyFormat="C">BHD-AED</mp:quotation> 
      </fxsp:pair>
     </fxsp:spot>
    </fx:forex>
   </mp:date>
  </mp:nickName>
 </xc:XmlCacheArea>
</xc:XmlCache>

我正在寻找一种做两件事的方法: 1.删​​除除了两个之外的所有元素 - > mp:ask和mp:bid 2.将这两个元素的数值更改为我在csv文件中的其他值。

预期输出

<xc:XmlCache xmlns:xc="XmlCache" xmlns:mp="mx.MarketParameters" xmlns:fx="mx.MarketParameters.Forex" xmlns:fxsp="mx.MarketParameters.Forex.Spot">
<xc:XmlCacheArea xc:value="MarketParameters">
<mp:nickName xc:value="MDS" xmlns:mp="mx.MarketParameters">
<mp:date xc:value="20130315">
<fx:forex xmlns:fx="mx.MarketParameters.Forex">
<fxsp:spot xmlns:fxsp="mx.MarketParameters.Forex.Spot">
<fxsp:pair xc:value="AUD/AED" xc:type="Fields">
<mp:ask xc:keyFormat="N">1.0000000</mp:ask> 
<mp:bid xc:keyFormat="N">1.0000000</mp:bid> 
</fxsp:pair>
<fxsp:pair xc:value="BHD/AED" xc:type="Fields">
<mp:ask xc:keyFormat="N">0.8264463</mp:ask> 
<mp:bid xc:keyFormat="N">0.8264463</mp:bid> 
</fxsp:pair>
</fxsp:spot>
</fx:forex>
</mp:date>
</mp:nickName>
</xc:XmlCacheArea>
</xc:XmlCache>

我们的想法是使用csv文件中提供的值更新输出xml中的值(第一个值是bid,第二个是ask)。如果需要,可以将csv文件转换为xml,这没有问题。

CSV file
AUD/AED;25;25
BHD/AED;20;20

该文件来自我们使用的应用程序。更改值后,目标是将文件重新导入应用程序。 我在xsl中尝试了很多东西,但我必须说我不知道​​如何才能让它工作。

somebode能帮忙吗?

由于

1 个答案:

答案 0 :(得分:0)

我建议您将CSV文件转换为XML。 XSLT显然最适合XML。此外,您几乎肯定必须使用XSLT 2.0来解析非XML文件。所以,为了这个答案的目的,我假设查找文件看起来像这样

<csv>
   <record code="AUD/AED" bid="25" ask="25" />
   <record code="BHD/AED" bid="20" ask="20" />
</csv>

在进行转换方面,如果您尚未进行转换,则应该在XSLT身份转换的基础上构建复制所有现有节点作为开始。

<xsl:template match="@*|node()">
  <xsl:copy>
    <xsl:apply-templates select="@*|node()"/>
  </xsl:copy>
</xsl:template>

这意味着您只需为要更改的节点/属性编写其他模板。

你说除了'bid'和'ask'之外你想要删除所有(叶子)元素,好吧,你可以写这样的模板,忽略所有其他的

<xsl:template match="fxsp:pair/*[not(self::mp:ask) and not(self::mp:bid)]" />

您需要的唯一其他模板是与未排除的任何其他元素下的文本节点匹配的模板(即现在只与您的'ask'和'bid'元素匹配)

<xsl:template match="fxsp:pair/*/text()">

在此范围内,您可以从“查找”文件中进行查找

<xsl:value-of select="document('lookup.xml')//record[@code=$code]/@*[local-name()=$attr]"/>

在这种情况下, $ code 设置为 fxsp:pair xc:value 的属性值, $ attr 是当前元素的名称('ask'或'bid')。

试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xc="XmlCache" xmlns:mp="mx.MarketParameters" xmlns:fx="mx.MarketParameters.Forex" xmlns:fxsp="mx.MarketParameters.Forex.Spot">
  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="fxsp:pair/*[not(self::mp:ask) and not(self::mp:bid)]" />

  <xsl:template match="fxsp:pair/@xc:type" />

  <xsl:template match="fxsp:pair/*/text()">
    <xsl:variable name="code" select="../../@xc:value" />
    <xsl:variable name="attr" select="local-name(..)" />
    <xsl:value-of select="document('lookup.xml')//record[@code=$code]/@*[local-name()=$attr]"/>
  </xsl:template>
</xsl:stylesheet>

注意,您可以将“文档”引用放在变量中,这可以简化事情(并确实提高效率)。也试试这个XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xc="XmlCache" xmlns:mp="mx.MarketParameters" xmlns:fx="mx.MarketParameters.Forex" xmlns:fxsp="mx.MarketParameters.Forex.Spot">
  <xsl:output method="xml" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:variable name="lookup" select="document('lookup.xml')//record" />

  <xsl:template match="@*|node()">
    <xsl:copy>
      <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="fxsp:pair/*[not(self::mp:ask) and not(self::mp:bid)]" />

  <xsl:template match="fxsp:pair/@xc:type" />

  <xsl:template match="fxsp:pair/*/text()">
    <xsl:variable name="code" select="../../@xc:value" />
    <xsl:variable name="attr" select="local-name(..)" />
    <xsl:value-of select="$lookup[@code=$code]/@*[local-name()=$attr]"/>
  </xsl:template>
</xsl:stylesheet>