XPath 1.0:选择具有给定父节点的所有子节点,如果父节点没有这样的子节点,则选择空?

XPath 1.0:选择具有给定父节点的所有子节点,如果父节点没有这样的子节点,则选择空?,xpath,vtd-xml,Xpath,Vtd Xml,使用XPath 1.0和下面的XML,如何选择所有具有“b”父节点的“c”节点,如果“b”父节点没有“c”节点,则选择“”,即获取{“c1”、“”、“c3”}作为结果节点集(按文档顺序) 我正在使用VTD-XML2.11(Java),我正在寻找一个XPath计算,它将返回上述结果,而不会循环 <a> <b> <c>c1</c> </b> <b/> <b> <c>c3&l

使用XPath 1.0和下面的XML,如何选择所有具有“b”父节点的“c”节点,如果“b”父节点没有“c”节点,则选择“”,即获取
{“c1”、“”、“c3”}
作为结果节点集(按文档顺序)

我正在使用VTD-XML2.11(Java),我正在寻找一个XPath计算,它将返回上述结果,而不会循环

<a>
  <b>
    <c>c1</c>
  </b>
  <b/>
  <b>
    <c>c3</c>
  </b>
</a>

c1
c3
我浏览了这些问题,找到了一些有趣的建议,比如奥利弗·贝克尔的方法,但到目前为止我还没有找到解决办法

任何帮助都将不胜感激


谢谢。

你用什么来评估这些XPath?我想不出一个好的方法,但是根据您使用的方法,可以很容易地选择所有
b
s,对它们进行迭代,并对每个值使用c值或空白值

这不是一个很好的方法,但它适用于您的示例输入:

//b/c | //b[not(*)] | //b[not(c) and *]/text()
<root>
  <item>c1</item>
  <item></item>
  <item>c3</item>
</root>
解释是:

  • 选择a
    b
    b下的所有
    c
    s
  • 如果没有子元素,请选择任何
    b
    元素本身
  • 选择没有子项的任何
    b
    s的第一个文本节点
假设具有子元素的任何
b
都将至少有一个文本节点,并且其中的第一个节点将完全是空白,那么这将起作用

使用XSLT进行验证:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <root>
      <xsl:for-each select="//b/c | //b[not(*)] | //b[not(c) and *]/text()[1]">
        <item>
          <xsl:value-of select="."/>
        </item>
      </xsl:for-each>
    </root>
  </xsl:template>
</xsl:stylesheet>

在示例输入上运行时的输出:

//b/c | //b[not(*)] | //b[not(c) and *]/text()
<root>
  <item>c1</item>
  <item></item>
  <item>c3</item>
</root>

c1
c3
像这样的东西

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.XPath;
using System.IO;

namespace Xpath
{
    class Program
    {
        static void Main(string[] args)
        {

            string xml = @"<a>
              <b>
                <c>c1</c>
              </b>
              <b/>
              <b>
                <c>c3</c>
              </b>
              <b>x</b>
            </a>";

            XmlDocument doc = new XmlDocument();
            doc.LoadXml(xml);

            string xpath = "//b/c/text()|//b[count(child::*) = 0]|//b[count(child::*) = 0]/text()";

            StringReader stringReader = new StringReader(xml);
            XmlReader xmlReader = XmlReader.Create(stringReader);

            XPathDocument xpathDoc = new XPathDocument(xmlReader);

            XPathNavigator xpathNav = xpathDoc.CreateNavigator();
            XPathNodeIterator xpathIter = xpathNav.Select(xpath);

            foreach (XPathNavigator navigator in xpathIter)
            {
                if (navigator.ValueType == typeof(string))
                {
                    Console.WriteLine("'" + navigator.Value + "'");
                }
            }
        }
    }
}

不幸的是,当我使用VTD-XML2.11(Java)运行它时,它会返回
“c1”、“c3”和“
。我不认为这是XPath应该产生的结果(它应该按照文档顺序选择节点),但我想不出比这更好的方法了。您不想使用循环有什么原因吗?有没有办法用VTD-XML做到这一点?不知道为什么VTD-XML不按文档顺序选择节点在这种情况下,好问题。基本上,我希望使用一个通用循环来计算多个XPath表达式,每个表达式都会产生一个结果列表,因此不能根据表达式使用自定义解析逻辑。当我运行它时(使用我的原始XML),这会返回
“c1”、“c3”、““”、”
,不幸的是,使用VTD-XML 2.11(Java)。是否希望xpath返回节点集或字符串作为结果?我正在寻找xpath求值以返回由
{“c1”、“”、“c3”}
字符串组成的节点集。节点的顺序重要吗?是,(文档)顺序重要。出于性能原因,vtd xml不能保证文档的顺序,除非评估过程自然地导致它。。。我将不得不考虑这个问题,看看我是否能为你提供一些答案