XPath,用于访问具有特殊字符

时间:2016-07-03 18:59:51

标签: java xml xpath

我正在尝试访问属性值,但属性名称包含特殊字符,例如:

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <row>
    <ELEMENT1 at:it="true">W</ELEMENT1>------
    <ELEMENT2>IN</ELEMENT2>
    <ELEMENT3>RP</ELEMENT3>
    <ELEMENT4>KKK</ELEMENT4>
  </row>
  <row>
    <ELEMENT1 acón='sys'>2</ELEMENT1>------
    <ELEMENT2>ARQ</ELEMENT2>
    <ELEMENT3>MR</ELEMENT3>
    <ELEMENT4>AC</ELEMENT4>
  </row>
  <row>
     <ELEMENT1>3</ELEMENT1>
    <ELEMENT2>I</ELEMENT2>
    <ELEMENT3 at:it="true" >RP</ELEMENT3>------
    <ELEMENT4>KKK</ELEMENT4>
  </row>
  <row>
    <ELEMENT1>1</ELEMENT1>
    <ELEMENT2>CC</ELEMENT2>
    <ELEMENT3>XX</ELEMENT3>
    <ELEMENT4 eléct='false' >I</ELEMENT4>------
  </row>
  <row>
     <ELEMENT1>12</ELEMENT1>
    <ELEMENT2 at:it="true" >IN</ELEMENT2>------
    <ELEMENT3>3</ELEMENT3>
    <ELEMENT4></ELEMENT4>
  </row>
</root>

如果我更改属性的名称并删除它们的特殊字符,我可以访问它们:

at:it ------> atit
Acón ------> Acon
eléctr ------> elect

但是带有特殊字符的属性名称我无法使用XPath查询表达式访问它们。

如何将XML文件访问为具有特殊字符名称的属性值?

要将XML文件转换为DOM,我使用了Java6,javax.xml。,org.w3c.dom。

2 个答案:

答案 0 :(得分:1)

实现冒号(:should仅在元素或属性名称中使用(如果是名称空间前缀的一部分):

  

注意

     

XML建议[XML Names]中的命名空间赋予了意义   包含冒号字符的名称。因此,作者不应该使用   XML名称中的冒号,但名称空间除外,但是XML   处理器必须接受冒号作为名称字符。

所以,

/root/row/ELEMENT1/@at:it

将选择"true" ,只要您通过在XML中定义at名称空间前缀(首选)来更改XML,

<root xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:at="http://example.com/at">
  <row>
    <ELEMENT1 at:it="true">W</ELEMENT1>------
    <ELEMENT2>IN</ELEMENT2>
    <ELEMENT3>RP</ELEMENT3>
    <ELEMENT4>KKK</ELEMENT4>
  </row>
  <row>
    <ELEMENT1 acón='sys'>2</ELEMENT1>------
    <ELEMENT2>ARQ</ELEMENT2>
    <ELEMENT3>MR</ELEMENT3>
    <ELEMENT4>AC</ELEMENT4>
  </row>
  <row>
     <ELEMENT1>3</ELEMENT1>
    <ELEMENT2>I</ELEMENT2>
    <ELEMENT3 at:it="true" >RP</ELEMENT3>------
    <ELEMENT4>KKK</ELEMENT4>
  </row>
  <row>
    <ELEMENT1>1</ELEMENT1>
    <ELEMENT2>CC</ELEMENT2>
    <ELEMENT3>XX</ELEMENT3>
    <ELEMENT4 eléct='false' >I</ELEMENT4>------
  </row>
  <row>
     <ELEMENT1>12</ELEMENT1>
    <ELEMENT2 at:it="true" >IN</ELEMENT2>------
    <ELEMENT3>3</ELEMENT3>
    <ELEMENT4></ELEMENT4>
  </row>
</root>

或指示您的XML处理器忽略XML命名空间( 是最佳做法)。

接下来的两个案件很好:

/root/row/ELEMENT1/@acón
如果你的XPath处理器支持UTF-8编码,那么

会毫无问题地选择"sys"

/root/row/ELEMENT4/@eléct

会同样选择"false"

答案 1 :(得分:1)

我尝试使用Java 6,并且使用重音访问属性没有问题。冒号是一种特殊情况,因为它用于表示带有名称空间前缀的元素/属性名称。 XML不使用名称空间,否则前缀at有名称空间声明。

XML解析器有一个开关,可以将冒号视为名称的一部分,但XPath引擎始终可以识别名称空间。但通过一个小技巧,它也是可能的:

File xmlFile = new File("in.xml");
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
// Parse without namespaces. Otherwise parsing leads to an error 
// because there is no namespace declaration for prefix 'at'.
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(xmlFile);

XPathFactory xPathfactory = XPathFactory.newInstance();
XPath xpath = xPathfactory.newXPath();

XPathExpression expr1 = xpath.compile("/root/row/ELEMENT1/@acón");
//XPathExpression expr2 = xpath.compile("/root/row/ELEMENT1/@at:it");  Doesn't work!
XPathExpression expr2 = xpath.compile("/root/row/ELEMENT1/@*[name() = 'at:it']");
XPathExpression expr3 = xpath.compile("/root/row/ELEMENT4/@eléct");

System.out.println((String) expr1.evaluate(doc, XPathConstants.STRING));
System.out.println((String) expr2.evaluate(doc, XPathConstants.STRING));
System.out.println((String) expr3.evaluate(doc, XPathConstants.STRING));

输出结果为:

sys
true
false