更改节点的值
检查一下 XML 文档的常量是有用的,但是在处理全功能的应用程序时,您可能需要更改数据以添加、编辑、移动或删除信息。编辑数据的能力对创建新 XML 文档的过程也是至关重要的。这类更改中最简单的情况就是更改元素的文本内容。
这里的目标是更改某个元素的文本节点的值,在此例中是将每个 order 的 status 设置为“processed”,然后向屏幕打印新的值。
对 changeOrder()方法的调用使用起始节点(root)以及要更改的元素名称和要更改到的目标值作为参数。
changeOrder()首先检查节点的名称,以确定它是否为要编辑的元素之一。如果是,应用程序需要更改的不是这个节点的值,而是这个节点的第一个孩子的值,因为这第一个孩子才是实际包含内容的文本节点。
在任一种情况下,应用程序都要检查每个孩子,就像大它在第一次单步调试文档时所做一样。
当完成更改时,更改后的值将使用 getElementsByTagName() 来检查。这个方法返回具有指定名称(比如 status)的所有孩子的列表。然后应用程序就能够检查该列表中的值,以检验 changeOrder() 方法调用的有效性。
...
public class OrderProcessor {
private static void changeOrder (Node start,
String elemName,
String elemValue)
{
if (start.getNodeName().equals(elemName)) {
start.getFirstChild().setNodeValue(elemValue);
}
for (Node child = start.getFirstChild();
child != null;
child = child.getNextSibling())
{
changeOrder(child, elemName, elemValue);
}
}
...
public static void main (String args[]) {
...
// Change text content
changeOrder(root, "status", "processing");
NodeList orders = root.getElementsByTagName("status");
for (int orderNum = 0;
orderNum < orders.getLength();
orderNum++)
{
System.out.println(orders.item(orderNum)
.getFirstChild().getNodeValue());
}
}
}
添加节点:准备数据
与更改现有节点不同,有时添加一个节点是必要的,而您可以通过多种方式来做到这点。在本例中,应用程序汇总
每个order的价格,然后添加一个total元素。它通过接受每个订单,循环迭代它的每件商品以获取商品价
格,然后汇总这些价格,从而获得总价格。然后应用程序向订单添加一个新的元素(参加下面的代码清单)。
首先,应用程序检索order元素,就像它检索status元素一样。然后它循环迭代这其中的每个元素。
对于这其中的每个order,应用程序都需要其item元素的一个NodeList,因此应用程序必须首先
将orderNode强制转换为Element,才能使用getElementsByTagName()。
然后应用程序可以循环迭代item元素,以寻找选定的order。应用程序将每个 item 强制转换为Element,以便能够根据名称检索price和qty。它是通过使用getElementsByTagName()来进行的,因为每件商品只有一个名称,它可以直接转到item(0),即结果NodeList中的第一个
条目。这第一个条目表示price(或qty)元素。它就是从那里获得文本节点的值的。
文本节点的值是String值,应用程序然后会将它转换为一个double值,以允许进行必要的数学运算。
当应用程序检查完每个订单的每件商品时,total就是一个代表总价格的double值。然后total
被转换为String值,以便能将它用作新元素的内容,<total>最终加入了order。
... changeOrder(root, "status", "processing"); NodeList orders = root.getElementsByTagName("order"); for (int orderNum = 0; orderNum < orders.getLength(); orderNum++) { Element thisOrder = (Element)orders.item(orderNum); NodeList orderItems = thisOrder.getElementsByTagName("item"); double total = 0; for (int itemNum = 0; itemNum < orderItems.getLength(); itemNum++) { // Total up cost for each item and // add to the order total //Get this item as an Element Element thisOrderItem = (Element)orderItems.item(itemNum); //Get pricing information for this Item String thisPrice = thisOrderItem.getElementsByTagName("price").item(0) .getFirstChild().getNodeValue(); double thisPriceDbl = new Double(thisPrice).doubleValue(); //Get quantity information for this Item String thisQty = thisOrderItem.getElementsByTagName("qty").item(0) .getFirstChild().getNodeValue(); double thisQtyDbl = new Double(thisQty).doubleValue(); double thisItemTotal = thisPriceDbl*thisQtyDbl; total = total + thisItemTotal; } String totalString = new Double(total).toString(); } ...添加节点:向文档添加节点您可以用许多方法创建新Node,而本例将使用其中的几种方法。 首先,Document对象能够使用totalString作为值来创建新的文本节点。新的Node现在已经存在了,但是还没在任何地方实际
连接到Document。新的total元素是以类似的方式创建的,起初也没有实质性的内容。添加节点的另一种方法是使用appendChild(),就像这里将节点添加到total元素一样。最后,应用程序可以使用insertBefore()来向Document添加新的元素,同时指定新的Node,然后指定新Node之后的那个Node。单步调试文档将检验这些更改。... changeOrder(root, "status", "processing"); NodeList orders = root.getElementsByTagName("order"); for (int orderNum = 0; orderNum < orders.getLength(); orderNum++) { ... String totalString = new Double(total).toString(); Node totalNode = doc.createTextNode(totalString); Element totalElement = doc.createElement("total"); totalElement.appendChild(totalNode); thisOrder.insertBefore(totalElement, thisOrder.getFirstChild()); } stepThrough(root); ...删除节点与替换元素的文本不同,应用程序可以将它一起删除。在这个例子中,应用程序检查商品是否有现货
。如果没有,它将从订单中删除该商品,而不是将其添加到汇总中。在将商品成本添加到价款汇总中之前,应用程序会检查instock属性的值。如果该值为N,则不
是将它添加到价款汇总中,而是将它完全删除。为此,它使用了removeChild()方法,不过首
先使用了getParentNode()来确定orderItem的父节点。实际的Node从文档中删除了
,但是该方法还是将它作为一个对象返回,以便能根据需要移动它。... //Get this item as an Element Element thisOrderItem = (Element)orderItems.item(itemNum); if (thisOrderItem.getAttributeNode("instock") .getNodeValue().equals("N")) { Node deadNode = thisOrderItem.getParentNode().removeChild(thisOrderItem); } else { //Get pricing information for this Item String thisPrice = thisOrderItem.getElementsByTagName("price").item(0) .getFirstChild().getNodeValue(); ... total = total + thisItemTotal; } } String totalString = new Double(total).toString(); ...替换节点因为某件商品订货不足(backordered)而删除该商品是没有多大意义的。相反,应用程序会使用
一个backordered项来替换它。与使用删除属性removeChild()不同的是,应用程序简单地使用了replaceChild()。注意在此例
中,该方法还会返回旧的节点,以便能根据需要将它移往别处,或许是移到一个新Document,
该 Document 列出所有订单不足的商品。注意由于没有内容被添加到该元素,因此它是一个空元素。空元素没有内容,并且可以用一种特殊的简
写来表示:
<backordered />斜线(
/)消除了对结束标签(</backordered>)的需要。... if (thisOrderItem.getAttributeNode("instock") .getNodeValue().equals("N")) { Element backElement = doc.createElement("backordered"); Node deadNode = thisOrderItem.getParentNode() .replaceChild(backElement, thisOrderItem); } else { ...创建和设置属性没有标志表明一个backordered元素是什么商品,那该怎么正确处理它呢?纠正信息缺乏的方法之一
是向元素添加属性。应用程序首先创建一个
itemid属性。接下来,它根据原先的item元素确定itemid的值,然后
再自己设置该属性的值。最后,它把该元素添加到文档,就像以前一样。... if (thisOrderItem.getAttributeNode("instock") .getNodeValue().equals("N")) { Element backElement = doc.createElement("backordered"); backElement.setAttributeNode(doc.createAttribute("itemid")); String itemIdString = thisOrderItem.getAttributeNode("itemid").getNodeValue(); backElement.setAttribute("itemid", itemIdString); Node deadNode = thisOrderItem.getParentNode().replaceChild(backElement, thisOrderItem); } else { ...如果具有该名称的节点不存在,setAttribute()就会创建一个属性节点。
应用程序还可以删除属性。例如,在输出中显示客户信用限额信息也许是不可取的,因此应用程序可以
临时地将该属性从文档中删除。删除信息是相当简单的,只需使用
removeAttribute()来删除数据。... Element thisOrder = (Element)orders.item(orderNum); Element customer = (Element)thisOrder.getElementsByTagName("customerid") .item(0); customer.removeAttribute("limit"); NodeList orderItems = thisOrder.getElementsByTagName("item"); ...
1820

被折叠的 条评论
为什么被折叠?



