2014-10-24 2 views
0

Будучи неопытным в Java и манипулирование XML, я застрял в проблеме.Анализ нескольких XML-документов в Java

Рассмотрим 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 = "xxx".

Следующий код заставляет меня близко на приведенном выше примере XML, но есть несколько вопросов:

  1. Это требует жестко закодированные XPaths поэтому не может повторно использоваться в различных документах
  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); 
    

Я надеялся, что кто-то может мне точку в правильном направлении или дать мне некоторые са который может помочь мне достичь результата, который я получаю после.

ответ

0

Пожалуйста, ознакомьтесь с этим обновленным ответом, и я сделал это, чтобы прочитать все атрибуты и их значения. вам нужно скачать файл sax2r2.jar, который вы получите на сайте this.

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(); 
     } 
    } 
} 
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(); 
    } 
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 коды.

Смежные вопросы