解析xml时,需要校验节点是不是闭合,如必须有与之对应,用数据结构实现比较好
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解析xml时,需要校验节点是不是闭合,如必须有与之对应,用数据结构实现比较好相关的知识,希望对你有一定的参考价值。
参考技术A假设有一个xml文件如下:
<name>
</name>
<age>
</age>
</student>
可以看到父元素是<student>,该父元素嵌套有两个子元素,分别是<name>和<age>。如果需要检验节点是否闭合,可以设置一个栈。每读入一个开始标记(如<student>和<name>),就作为一个新的更急迫的期待压入栈中。而每读入一个结束标记(如</student>和</name>),则或者使置于栈顶的最急迫的期待得以消解,或者是不合法的情况。
比如当计算机接受了<student>时,可以先入栈,然后它期待着相应的结束标记</student>的出现。但是等来的是<name>,<name>期待匹配的程度更加急迫,所以再将<name>入栈,然后接受</name>后,该期待得到了满足,可以消解,即出栈。然后读入<age>和</age>,最后读入</student>,所有的期待都消解,说明节点是闭合的,该xml文件正确。希望你能理解。
本回答被提问者和网友采纳 参考技术B 用栈的数据结构实现比较好。为啥在解析 XML 时获取空节点值
【中文标题】为啥在解析 XML 时获取空节点值【英文标题】:Why getting null node value while parsing XML为什么在解析 XML 时获取空节点值 【发布时间】:2013-12-22 05:15:12 【问题描述】:在解析下面的 XML 时。首先 url-malformed-exception
在解析代码时出现,而不是给出 xml 字符串,我使用了这段代码
Document doc=dBuilder.parse(newInputSource(newByteArrayInputStream(xmlResponse.getBytes("utf-8"))));
根据这个链接
java.net.MalformedURLException: no protocol
现在我将节点值设为 null 。我该如何克服这个问题。在 for 循环中的代码中,我已经提到节点的 null 值来自何处
我正在使用以下代码:
try
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new InputSource(new ByteArrayInputStream(xmlResponse.getBytes("utf-8"))));
//read this - https://***.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
doc.getDocumentElement().normalize();
System.out.println("Root element :" + doc.getDocumentElement().getNodeName());
XPath xPath = XPathFactory.newInstance().newXPath()
String expression = "/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product"
System.out.println(expression)
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(doc, XPathConstants.NODESET)
System.out.println("the size will be of the node list $nodeList.getLength()");
for (int i = 0; i < nodeList.getLength(); i++)
System.out.println(nodeList.item(i).getNodeValue()+"the value coming will be "); // here i am getting value null for each node
catch (Exception e)
e.printStackTrace(System.out);
解析 XML:
<?xml version="1.0"?>
<GetMatchingProductForIdResponse xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01">
<GetMatchingProductForIdResult Id="H5-9OSH-9NZ7" IdType="SellerSKU" status="Success">
<Products xmlns="http://mws.amazonservices.com/schema/Products/2011-10-01" xmlns:ns2="http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd">
<Product>
<Identifiers>
<MarketplaceASIN>
<MarketplaceId>ATVPDKIKX0DER</MarketplaceId>
<ASIN>B004FQLAH2</ASIN>
</MarketplaceASIN>
</Identifiers>
<AttributeSets>
<ns2:ItemAttributes xml:lang="en-US">
<ns2:Binding>Office Product</ns2:Binding>
<ns2:Brand>Konica-Minolta</ns2:Brand>
<ns2:Color>Y</ns2:Color>
<ns2:CPUSpeed Units="MHz">200</ns2:CPUSpeed>
<ns2:Department>Printers</ns2:Department>
<ns2:Feature>Amp Up your Output - The magicolor 3730DN business color laser printer outputs at speeds up to 25 ppm in both color and B&W which means you can keep up in just about any business environment.</ns2:Feature>
<ns2:Feature>Unparalleled Image Quality - High resolution 2400 (equivalent) x 600 dpi printing for great color and clarity in both images and text.</ns2:Feature>
<ns2:Feature>Happy Planet, Outstanding Printing - Simitri HD Toner with Biomass allows for outstanding printing with the environment in mind.</ns2:Feature>
<ns2:Feature>Connect quicker - Why wait? Standard Ethernet and high-speed USB 2.0 gets you connected faster than ever before.Specifications</ns2:Feature>
<ns2:Feature>Type - Full-Color Laser Printer</ns2:Feature>
<ns2:ItemDimensions>
<ns2:Height Units="inches">13.62</ns2:Height>
<ns2:Length Units="inches">20.47</ns2:Length>
<ns2:Width Units="inches">16.50</ns2:Width>
<ns2:Weight Units="pounds">56.22</ns2:Weight>
</ns2:ItemDimensions>
<ns2:IsAutographed>false</ns2:IsAutographed>
<ns2:IsMemorabilia>false</ns2:IsMemorabilia>
<ns2:Label>Konica</ns2:Label>
<ns2:ListPrice>
<ns2:Amount>449.00</ns2:Amount>
<ns2:CurrencyCode>USD</ns2:CurrencyCode>
</ns2:ListPrice>
<ns2:Manufacturer>Konica</ns2:Manufacturer>
<ns2:Model>A0VD017</ns2:Model>
<ns2:NumberOfItems>1</ns2:NumberOfItems>
<ns2:OperatingSystem>Windows XP, Vista, 7</ns2:OperatingSystem>
<ns2:OperatingSystem>Mac X 10.2.8, 10.6+</ns2:OperatingSystem>
<ns2:PackageDimensions>
<ns2:Height Units="inches">19.00</ns2:Height>
<ns2:Length Units="inches">24.20</ns2:Length>
<ns2:Width Units="inches">22.00</ns2:Width>
<ns2:Weight Units="pounds">65.30</ns2:Weight>
</ns2:PackageDimensions>
<ns2:PackageQuantity>1</ns2:PackageQuantity>
<ns2:PartNumber>A0VD017</ns2:PartNumber>
<ns2:ProductGroup>CE</ns2:ProductGroup>
<ns2:ProductTypeName>PRINTER</ns2:ProductTypeName>
<ns2:Publisher>Konica</ns2:Publisher>
<ns2:SmallImage>
<ns2:URL>http://ecx.images-amazon.com/images/I/21qN3BU-BHL._SL75_.jpg</ns2:URL>
<ns2:Height Units="pixels">75</ns2:Height>
<ns2:Width Units="pixels">75</ns2:Width>
</ns2:SmallImage>
<ns2:Studio>Konica</ns2:Studio>
<ns2:Title>Konica Minolta Magicolor 3730DN Color Laser Printer 24PPM 2400X600DPI ENET USB 2.0</ns2:Title>
</ns2:ItemAttributes>
</AttributeSets>
<Relationships/>
<SalesRankings/>
</Product>
</Products>
</GetMatchingProductForIdResult>
<ResponseMetadata>
<RequestId>0b508338-3afe-4178-adc4-60c9c8448987</RequestId>
</ResponseMetadata>
</GetMatchingProductForIdResponse>
【问题讨论】:
【参考方案1】:DOM 中的getNodeValue
方法被定义为始终为元素节点返回null
(有关详细信息,请参见the JavaDoc page for org.w3c.dom.Node
顶部的表格)。如果你想要元素内的文本,那么你应该使用getTextContent()
。
您在此答案的评论中添加了第二个问题,询问如何使用 XPath 搜索具有命名空间前缀(例如 ns2:
)的节点。 XPath 1.0 处理命名空间的方式是,无前缀名称总是引用不在命名空间中的节点,如果您想引用命名空间节点,那么您必须提供命名空间 URI 到前缀的绑定(在 javax.xml.xpath
中是工作NamespaceContext
) 然后在表达式中使用这些前缀。您在表达式中使用的前缀不必与使用的原始文档相同,只要它们绑定到正确的 URI。
因此您使用的原始 XPath:
/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product
实际上不应该匹配任何内容,因为您的文档中的GetMatchingProductForIdResponse
等元素 在一个命名空间中,但是您侥幸逃脱,因为DocumentBuilderFactory
默认情况下不支持命名空间。正确的做法是使用命名空间感知解析器,并为 XPath 引擎提供合适的命名空间上下文。不幸的是,核心 Java 库中没有 NamespaceContext 的默认实现,但 Spring 提供了一个方便的 SimpleNamespaceContext
实现,如果您不想自己动手,可以使用。
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
dbFactory.setNamespaceAware(true); // parse with namespaces
DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
Document doc = dBuilder.parse(new InputSource(new ByteArrayInputStream(xmlResponse.getBytes("utf-8"))));
doc.getDocumentElement().normalize();
XPath xPath = XPathFactory.newInstance().newXPath();
SimpleNamespaceContext nsCtx = new SimpleNamespaceContext();
xPath.setNamespaceContext(nsCtx);
nsCtx.bindNamespaceUri("prod", "http://mws.amazonservices.com/schema/Products/2011-10-01");
nsCtx.bindNamespaceUri("ns2", "http://mws.amazonservices.com/schema/Products/2011-10-01/default.xsd");
String expression = "/prod:GetMatchingProductForIdResponse/prod:GetMatchingProductForIdResult/prod:Products/prod:Product/prod:AttributeSets/ns2:ItemAttributes/ns2:Binding";
// ...
【讨论】:
String expression = "/GetMatchingProductForIdResponse/GetMatchingProductForIdResult/Products/Product/AttributeSets/ns2:ItemAttributes/ns2:Binding"
使用此代码对 NodeList 进行了评估,直到 ns2:binding NodeList nodeList = xPath.compile(expression).evaluate(doc, XPathConstants.NODESET)
NodeList 大小趋于零,为什么?如何获取节点 以上是关于解析xml时,需要校验节点是不是闭合,如必须有与之对应,用数据结构实现比较好的主要内容,如果未能解决你的问题,请参考以下文章
intellij idea如何快速将 xml 文件的所有展开的节点闭合
Groovy自定义 Xml 生成器 BuilderSupport ( nodeCompleted 方法获取节点闭合信息 )