【发布时间】:2011-12-01 05:55:16
【问题描述】:
我最近遇到了以下股票代码 XML 提要:
<?xml version="1.0" encoding="utf-8"?>
<BloombergOutput>
<BloombergOutput CreatedUtc="2011-08-11T20:40:50.8851936Z">
<Instruments>
<Instrument Symbol="BLL">
<Fields>
<Field1 Name="LastPrice">
<Value>35.550000</Value>
</Field1>
<Field2 Name="NetChangeOneDay">
<Value>+1.550000</Value>
</Field2>
<Field3 Name="LastCloseDate">
<Value>08/11/2011</Value>
</Field3>
<Field4 Name="LastClosePrice">
<Value>35.550000</Value>
</Field4>
<Field5 Name="UpdateDate">
<Value>08/11/2011</Value>
</Field5>
<Field6 Name="UpdateTime">
<Value>16:15:03</Value>
</Field6>
<Field7 Name="LongName">
<Value>Ball Corp</Value>
</Field7>
<Field8 Name="Name">
<Value>BALL CORP</Value>
</Field8>
<Field9 Name="PriceSource">
<Value>US</Value>
</Field9>
<Field10 Name="SymbolType">
<Value>Common Stock</Value>
</Field10>
</Fields>
</Instrument>
</Instruments>
</BloombergOutput>
</BloombergOutput>
我想使用 XSLT 将此提要转换为没有不必要的标记嵌套、具有更多描述性元素名称以及截断过长数字以使其小数点后只有两个数字的东西。这是我想出的 XSLT:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="no" indent="yes"/>
<xsl:strip-space elements="*"/>
<!-- Identity Transform, modified to begin at the Instruments element -->
<xsl:template match="BloombergOutput/BloombergOutput/Instruments/@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- For each instrument, we grab the Symbol attribute and work on each child element -->
<xsl:template match="Instrument">
<Instrument>
<Symbol><xsl:value-of select="@Symbol" /></Symbol>
<xsl:apply-templates select="Fields/*" mode="fields" />
</Instrument>
</xsl:template>
<!-- For each child field, we create a newly-named one and give it a value -->
<xsl:template match="node()" mode="fields">
<xsl:variable
name="FieldName"
select="@Name" />
<xsl:variable
name="Value"
select="Value" />
<xsl:element name="{$FieldName}">
<xsl:choose>
<!-- For these fields, we only want to preserve to spots after the decimal point -->
<xsl:when test="$FieldName='LastPrice' or $FieldName='NetChangeOneDay' or $FieldName='LastClosePrice'">
<xsl:value-of select="concat(substring-before($Value, '.'), '.', substring(substring-after($Value, '.'), 1, 2))" />
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$Value" />
</xsl:otherwise>
</xsl:choose>
</xsl:element>
</xsl:template>
</xsl:stylesheet>
...产生这个输出:
<?xml version="1.0"?>
<BloombergOutput>
<BloombergOutput>2011-08-11T20:40:50.8851936Z
<Instruments>
<Instrument>
<Symbol>BLL</Symbol>
<LastPrice>35.55</LastPrice>
<NetChangeOneDay>+1.55</NetChangeOneDay>
<LastCloseDate>08/11/2011</LastCloseDate>
<LastClosePrice>35.55</LastClosePrice>
<UpdateDate>08/11/2011</UpdateDate>
<UpdateTime>16:15:03</UpdateTime>
<LongName>Ball Corp</LongName>
<Name>BALL CORP</Name>
<PriceSource>US</PriceSource>
<SymbolType>Common Stock</SymbolType>
</Instrument>
</Instruments>
</BloombergOutput>
</BloombergOutput>
虽然这几乎是我想要的,但也存在一些问题:
- 顶部的附加
BloombergOutput元素被保留;此外,它的CreatedUtc参数以一种相当奇怪的方式保留。我最初的意图是完全删除不必要的BloombergOutput标签。 - 我已成功插入添加的
Instrument标签。 但是,Instruments被保留,我没有明确表示。 我知道身份转换带来了它,因为我没有 告诉它走开,但如果我想要不同的开场元素怎么办 (比如StockQuote)? - 我的目的是要善于使用身份转换。 但是,我不确定我的匹配修改是否正确 完成我正在做的事情的方法。
总体而言,我正在寻求您关于如何改进这一点的专家建议。随意告诉我,我正在尝试在不属于它的设计模式中进行干扰。 :)
非常感谢。
【问题讨论】: