需要帮助以递归方式从xml获取数据

时间:2017-06-14 01:42:16

标签: java xml xslt

我试图通过XSLT递归地读取跟随xml属性的数据。

这是我的Sample XML数据!!

<FIXML .....">
  <Batch ....>
    <MktDef MktID="XEUR" MktSegID="14" EfctvBizDt="2017-05-11" NxtEfctvBizDt="2017-05-15" MktSeg="CONF" MarketSegmentDesc="FUT 8-13 Y. SWISS GOV.BONDS 6%" Sym="CH0002741988" ParentMktSegmID="FBND" Ccy="CHF" MktSegStat="1" USFirmFlag="Y" PartID="2">
     .
     .
     .
    </MktDef>
    <MktDef MktID="XEUR" MktSegID="19629" EfctvBizDt="2017-05-11" NxtEfctvBizDt="2017-05-15" MktSeg="FBON" MarketSegmentDesc="EURO BONO FUTURE 8,5-10,5 YEAR" Sym="DE000A163W29" ParentMktSegmID="FBND" Ccy="EUR" MktSegStat="1" USFirmFlag="Y" PartID="2">
     .
     .
     .
     </MktDef>
     .
     .
     .

这是我的XSLT

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" >
<xsl:output method="text" omit-xml-declaration="yes" indent="no"/>
<xsl:template match="/">
 MktID,MktSegID,EfctvBizDt,NxtEfctvBizDt,MktSeg,MarketSegmentDesc,Sym,ParentMktSegmID,Ccy,MktSegStat,USFirmFlag,PartID
<xsl:for-each select="/">
<xsl:value-of select="concat(ancestor::FIXML/Batch/MktDef/@MktID,',',ancestor::FIXML/Batch/MktDef/@MktSegID,',',ancestor::FIXML/Batch/MktDef/@EfctvBizDt,',',ancestor::FIXML/Batch/MktDef/@NxtEfctvBizDt,',',ancestor::FIXML/Batch/MktDef/@MktSeg,',',ancestor::FIXML/Batch/MktDef/@MarketSegmentDesc,',',ancestor::FIXML/Batch/MktDef/@Sym,',',ancestor::FIXML/Batch/MktDef/@ParentMktSegmID,',',ancestor::FIXML/Batch/MktDef/@Ccy,',',ancestor::FIXML/Batch/MktDef/@MktSegStat,',',ancestor::FIXML/Batch/MktDef/@USFirmFlagt,',',ancestor::FIXML/Batch/MktDef/@PartID,'&#xA;')"/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>

这是我的Java代码..

class Xml2Csv {

    public static void main(String args[]) throws Exception {
        File stylesheet = new File("style.xsl");
        //File xmlSource = new File("Testing-1.xml");
        File xmlSource = new File("95FILRDF01PUBLI20170511XEUR6NJ92000.xml");

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.parse(xmlSource);

        StreamSource stylesource = new StreamSource(stylesheet);
        Transformer transformer = TransformerFactory.newInstance().newTransformer(stylesource);
        Source source = new DOMSource(document);
        System.out.println(source.toString());
        System.out.println("Hello");
        Result outputTarget = new StreamResult(new File("MktDef.csv"));
        transformer.transform(source, outputTarget);

    }
}

我正在解析此xml并尝试从MktDef属性获取数据并将其存储在CSV中,如下所示,

MktID   MktSegID    EfctvBizDt  NxtEfctvBizDt   MktSeg  MarketSegmentDesc   Sym ParentMktSegmID Ccy MktSegStat  USFirmFlag  PartID
XEUR    14  5/11/2017   5/15/2017   CONF    FUT 8-13 Y. SWISS GOV.BONDS 6%  CH0002741988    FBND    CHF 1       2
XEUR    14  5/11/2017   5/15/2017   CONF    FUT 8-13 Y. SWISS GOV.BONDS 6%  CH0002741988    FBND    CHF 1       2
XEUR    14  5/11/2017   5/15/2017   CONF    FUT 8-13 Y. SWISS GOV.BONDS 6%  CH0002741988    FBND    CHF 1       2
XEUR    14  5/11/2017   5/15/2017   CONF    FUT 8-13 Y. SWISS GOV.BONDS 6%  CH0002741988    FBND    CHF 1       2
.
.
.

我现在面临的问题是我只是一直获得第一个MktDef数据。我知道XSLT中存在一些逻辑问题。

我是处理XML和XSLT的新手,所以有人可以帮助我。 在此先感谢!

1 个答案:

答案 0 :(得分:1)

当您位于根节点(/)的模板内部时,选择for-each中的XPath与该节点相关。您想迭代每个MktDef元素,因此它应该是FIXML/Batch/MktDef

现在,在for-each中,上下文节点将变为每次迭代中的当前MkDef元素。因此,要获取当前MktDef元素属性的值,请从中选择相对属性:即@MktSegID

此外,如果您要发送文字文本(例如CSV标题行),请将其放在<xsl:text>元素内,以便您可以在模板中使用文本格式和缩进,并且不会将空白视为重要内容。

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format" >
  <xsl:output method="text" omit-xml-declaration="yes" indent="no"/>

  <xsl:template match="/">
    <xsl:text>MktID,MktSegID,EfctvBizDt,NxtEfctvBizDt,MktSeg,MarketSegmentDesc,Sym,ParentMktSegmID,Ccy,MktSegStat,USFirmFlag,PartID&#xA;</xsl:text>

    <xsl:for-each select="FIXML/Batch/MktDef">
      <xsl:value-of select="concat(@MktID,',',@MktSegID,',',@EfctvBizDt,',',@NxtEfctvBizDt,',',@MktSeg,',',@MarketSegmentDesc,',',@Sym,',',@ParentMktSegmID,',',@Ccy,',',@MktSegStat,',',@USFirmFlagt,',',@PartID,'&#xA;')"/>
    </xsl:for-each>
  </xsl:template>
</xsl:stylesheet>