缺乏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,但有一些问题:
无法获得第二个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 :(得分: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代码。