用Java解析多个XML文档

时间:2014-10-24 14:20:43

标签: java xml

缺乏Java经验和操纵XML我遇到了一个问题。

考虑这个XML片段:

<Rule Name="Assistant">
<RuleVersions>
    <Adjustments>
        <Adjustment Type="Bonus" BonusRateHourlyRate="10"></Adjustment>
    </Adjustments>
    <RuleVersion EffectiveDate="01/1/1753" ExpirationDate="01/1/3000">
        <Triggers>
            <SimpleValue Value="2204"/>
            <SimpleValue Value="2206"/>
        </Triggers>
    </RuleVersion>
</RuleVersions>

最终我需要实现的是提取规则名称,然后提取与之关联的每个属性以创建此输出:

Assistant Type Bonus
Assistant BonusRateHourlyRate 10
Assistant EffectiveDate 01/1/1753
Assistant ExpirationDate 01/1/3000
Assistant SimpleValue 2204
Assistant SimpleValue 2206

由于我需要传递数百个XML文件,所有这些文件都具有不同的结构,因此我的目标是创建一些可重复使用的代码,这些代码可以遍历每个文档并创建此输出,而不管其格式如何。一致的是名称(输出的第1列)将始终采用Name =&#34; xxx&#34;的格式。

以下代码让我了解上面的示例XML,但有一些问题:

  1. 它需要硬编码的xpath,因此不能在不同的文档中重复使用
  2. 无法获得第二个SimpleValue 2206

        FileInputStream file = new FileInputStream(new File("Output\\XML\\Test.xml"));
        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = builderFactory.newDocumentBuilder();
        Document xmlDocument = builder.parse(file);
        XPath xPath = XPathFactory.newInstance().newXPath();
        String TestCase = "";
        String name = "Rule/@Name";
        NodeList nodeList = (NodeList) xPath.compile(name).evaluate(xmlDocument, XPathConstants.NODESET);
    
        NodeList Type = (NodeList) xPath.compile("Rule/RuleVersions/Adjustments/Adjustment/@Type").evaluate(xmlDocument, XPathConstants.NODESET);
        NodeList BonusRateHourlyRate = (NodeList) xPath.compile("Rule/RuleVersions/Adjustments/Adjustment/@BonusRateHourlyRate").evaluate(xmlDocument, XPathConstants.NODESET);
        NodeList EffectiveDate = (NodeList) xPath.compile("Rule/RuleVersions/RuleVersion/@EffectiveDate").evaluate(xmlDocument, XPathConstants.NODESET);
        NodeList ExpirationDate = (NodeList) xPath.compile("Rule/RuleVersions/RuleVersion/@ExpirationDate").evaluate(xmlDocument, XPathConstants.NODESET);
        NodeList SimpleValue = (NodeList) xPath.compile("Rule/RuleVersions/RuleVersion/Triggers/SimpleValue/@Value").evaluate(xmlDocument, XPathConstants.NODESET);
    
        //Build the test cases file
        for (int i = 0; i < nodeList.getLength(); i++) {
            TestCase = TestCase + nodeList.item(i).getFirstChild().getNodeValue() + " Type " + Type.item(i).getNodeValue() + "\n";
            TestCase = TestCase + nodeList.item(i).getFirstChild().getNodeValue() + " BonusRateHourlyRate " + BonusRateHourlyRate.item(i).getNodeValue() + "\n";
            TestCase = TestCase + nodeList.item(i).getFirstChild().getNodeValue() + " EffectiveDate " + EffectiveDate.item(i).getNodeValue() + "\n";
            TestCase = TestCase + nodeList.item(i).getFirstChild().getNodeValue() + " ExpirationDate " + ExpirationDate.item(i).getNodeValue() + "\n";
            TestCase = TestCase + nodeList.item(i).getFirstChild().getNodeValue() + " SimpleValue " + SimpleValue.item(i).getNodeValue() + "\n";
    
        }
        System.out.println(TestCase);
    
  3. 我希望有人能指出我正确的方向,或者给我一些示例代码,以帮助我实现我追求的结果。

3 个答案:

答案 0 :(得分:0)

请立即查看此更新的答案我这样做是为了阅读所有属性及其值。您需要下载this网站上的sax2r2.jar文件。

import java.util.HashMap;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.helpers.DefaultHandler;

public class NewClass extends DefaultHandler {

    public static void main(String[] args) {

        try {
            SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
            SAXParser saxParser = saxParserFactory.newSAXParser();
            HashMap<String, String> map = new HashMap();
            String adjustment,ruleVersion,simpleValue;

            DefaultHandler defaultHandler = new DefaultHandler() {
                @Override
                public void startElement(String uri, String localName, String qname, Attributes attributes) {
                    if(attributes.getLength()>0)
                    {
                        int items = attributes.getLength();
                        System.out.println("Qualified Name:"+qname);
                        for(int i=0;i<items;i++)
                            System.out.println(attributes.getQName(i)+":"+attributes.getValue(i));
                    }

                }
            };
            saxParser.parse("e:\\abc.xml", defaultHandler);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

答案 1 :(得分:0)

看起来我有这个工作就像我需要它使用这个代码,它也删除了一些我不需要的额外部分,并在每行的开头添加名称:

try {
        SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
        SAXParser saxParser = saxParserFactory.newSAXParser();
        DefaultHandler defaultHandler = new DefaultHandler() {
            String ruleName = null;
            public void startElement(String uri, String localName, String qname, Attributes attributes) {

                if (attributes.getLength() > 0) {
                    int items = attributes.getLength();
                    for (int i = 0; i < items; i++) {
                        if ((qname.toString().equals("Header")) || (qname.toString().equals("Response"))) {
                            //Dont print out the XML headers
                        } else {
                            if (attributes.getQName(i).equals("Name")) {
                                ruleName = attributes.getValue(i);
                            } else {
                                //Don't reset the string;
                            }
                            System.out.println(ruleName+":"+qname + ":" + attributes.getQName(i) + ":" + attributes.getValue(i));
                        }
                    }
                }
            }
        };
        saxParser.parse(
                "Test.xml", defaultHandler);
    } catch (Exception e) {
        e.printStackTrace();
    }

答案 2 :(得分:0)

你真的不想为这样的问题编写低级Java代码。在XSLT或XQuery中做得更好。

您的示例输出无法以完全通用的方式实现,因为您以不同方式处理不同的元素,例如使用Adjustment / @Type输出属性名称,但使用SimpleValue / @ Value输出元素名称。我们假设这是一个疏忽。然后这个XSLT规则会给你你想要的东西:

<xsl:template match="Rule//@*">
  <xsl:value-of select="concat(ancestor::Rule/@Name, ' ', name(), ' ', .)"/>
</xsl:template>

这必须打败大量的Java代码。