【问题标题】:XPath to access an attribute value with a name that has special charactersXPath 访问具有特殊字符的名称的属性值
【发布时间】:2016-11-05 12:21:23
【问题描述】:

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

<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。

【问题讨论】:

  • 天使,欢迎来到 Stack Overflow。你来这里几个月了,问了 9 个问题,但还没有给accept 或upvote 任何答案。请阅读链接页面并考虑接受和/或支持对您有帮助的答案。谢谢。

标签: java xml xpath


【解决方案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

【讨论】:

  • ...谢谢,谢谢,我尝试过... factory.setNamespaceAware (false);....但仍然无法正常工作
【解决方案2】:

意识到冒号 (:) 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"。

【讨论】:

  • 谢谢,我试过 ... factory.setNamespaceAware (false); ...但它仍然无法正常工作...我也尝试过... factory.setNamespaceAware (true); ...和xsi:它。 ..但不行..我会继续测试
  • 如前所述,你真的不应该在元素或属性名称中使用冒号,除非它是命名空间前缀的一部分。尽管从技术上讲规范允许这样做,但听到您遇到问题我并不感到惊讶。真的,只是不要这样做。
【解决方案3】:
  1. 首先从节点获取属性,然后检查它们的名称。

  2. 类似: XPath xpath = XPathFactory.newInstance().newXPath(); NodeList nodes = (NodeList) xpath.evaluate(filteringExpression, xmlDocument, XPathConstants.NODESET);

  3. 然后遍历节点并为每个节点获取其属性: Node node = nodes.item(idx); NamedNodeMap nl = node.getAttributes();

  4. 然后遍历属性,如果名称匹配,则获取其值: Attr attr = (Attr) nl.item(i); if(attr.getName().equals(...)) String attributeValue = attr.getValue();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多