Возврат значений NULL для отсутствующих тегов с помощью EvaluateXpath в Java - PullRequest
1 голос
/ 16 июня 2020

Я получаю XML значений тегов путем оценки пути, предположим, у меня есть 3 тега с информацией о книге: Информация о книге состоит из: Имя - год - Автор и в 1 теге Имя автора пропущено и не входит в мой теги, я хочу иметь массив, который показывает 1 имя автора + нулевое значение, которое показывает, что 2 тега не были указаны, как показано ниже: Как вы видите, второй тег не содержит имени автора, а третий тег не имеет автора тег имени, как показано ниже: я очень признателен за любое руководство / подсказку / помощь. : -)

Автор: [John Smith, null, null]

Мой XML Файл:

<?xml version="1.0" encoding="UTF-8"?>
<perldata>
    <item key="book">
        <item key="name">My Book Name</item>
        <item key="year">2019</item>
        <item key="author">John Smith</item>
    </item>
    <item>
        <item key="name">Anonymous Book Name 1</item>
        <item key="year">2018</item>
        <item key="author"></item>
    </item>
    <item>
        <item key="name">Her Book Name</item>
        <item key="year">2018</item>
    </item>
</perldata>

Это показывает, что третий тег не состоит из тега имени автора. Я не знаю, как показать нулевое значение в EvaluateXpath: (действительно нужна помощь)

         String fileName="book.xml";
         Document document = getDocument(fileName);

                     // Defining Variables
                     //   String xpathExpression = "";
                       FileWriter fw = null; 
                       BufferedWriter bw = null; 
                       PrintWriter pw = null;

                    //Using Document Builder
         DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
                            documentBuilderFactory.setNamespaceAware(true);
                            DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
                            Document doc1 = documentBuilder.parse(fileName);


                         /*******Get attribute values using xpath******/
                        XPathFactory xpathFactory = XPathFactory.newInstance();
                        XPath xpath = xpathFactory.newXPath();
                try{
                        fw = new FileWriter("/root/Desktop/book.txt");
                        bw = new BufferedWriter(fw);
                        pw = new PrintWriter(bw)
                        pw.println("BookName: "+evaluateXpath(document, "/perldata/item[@key=book]/item[@key='name']/text()"));
                        pw.println("year: "+evaluateXpath(document, "/perldata/item[@key=book]/item[@key='year']/text()"))
                        pw.println("Author: "+evaluateXpath(document, "/perldata/item[@key=book]/item[@key='author']/text()"))
                pw.flush(); }
catch (IOException e) 
        { e.printStackTrace(); } } }

        private static List<String> evaluateXPath(Document document, String xpathExpression) throws Exception 
        {
            // Create XPathFactory object
            XPathFactory xpathFactory = XPathFactory.newInstance();

            // Create XPath object
            XPath xpath = xpathFactory.newXPath();

            List<String> values = new ArrayList<>();
            try
            {
                // Create XPathExpression object
                XPathExpression expr = xpath.compile(xpathExpression);

                // Evaluate expression result on XML document
                NodeList nodes = (NodeList) expr.evaluate(document, XPathConstants.NODESET);

                for (int i = 0; i < nodes.getLength(); i++) {
                    values.add(nodes.item(i).getNodeValue());
                }

            } catch (XPathExpressionException e) {
                e.printStackTrace();
            }

            return values;
        }


        private static Document getDocument(String fileName) throws Exception 
        {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setNamespaceAware(true);
            DocumentBuilder builder = factory.newDocumentBuilder();
            Document doc = builder.parse(fileName);
            return doc;
        }

        }

1 Ответ

1 голос
/ 19 июня 2020

Сводка :

Обрежьте текстовое содержимое тега и проверьте, пуста ли результирующая строка.

Подробности :

XML в вопросе содержит только один тег, содержащий key="book". Я предполагаю, что все 3 раздела должны иметь это, поэтому мы знаем, что каждый представляет собой книгу.

Поэтому я предполагаю, что у вас есть файл XML, подобный приведенному ниже, который включает один пустой тег «автор» и один полностью отсутствующий тег «автор»:

<?xml version="1.0" encoding="UTF-8"?>
<perldata>
    <item key="book">
        <item key="name">My Book Name</item>
        <item key="year">2019</item>
        <item key="author">John Smith</item>
    </item>
    <item key="book">
        <item key="name">Anonymous Book Name 1</item>
        <item key="year">2018</item>
        <item key="author"></item>
    </item>
    <item key="book">
        <item key="name">Her Book Name</item>
        <item key="year">2018</item>
    </item>
    <item key="book">
        <item key="name">Another Book Name</item>
        <item key="year">2019</item>
        <item key="author">Jane Jones</item>
    </item>
</perldata>

Исходя из вышеизложенного, вы можете распечатать все имена (включая null имена) следующим образом:

File file = new File("C:/tmp/Book2.xml");
FileInputStream fis = new FileInputStream(file);
DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = builderFactory.newDocumentBuilder();
Document xmlDocument = builder.parse(fis);
XPath xPath = XPathFactory.newInstance().newXPath();
NodeList bookNodes = (NodeList) xPath.compile("//item[@key='book']")
        .evaluate(xmlDocument, XPathConstants.NODESET);

List<String> authors = new ArrayList();

for (int i = 0; i < bookNodes.getLength(); i++) {
    Node bookNode = bookNodes.item(i);
    Node authorNode = (Node) xPath.compile("./item[@key='author']")
            .evaluate(bookNode, XPathConstants.NODE);

    if (authorNode == null) {
        authors.add(null);
    } else {
        String s = authorNode.getTextContent().trim();
        authors.add(s.isEmpty() ? null : s);
    }
}
System.out.println(authors);

Окончательная инструкция печати дает следующее:

[John Smith, null, null, Jane Jones]

Дополнительные примечания:

Это проходит через все разделы <item key="book"> в файле. Затем для каждого раздела он выполняет этот целевой поиск, но только внутри этого раздела :

Node authorNode = (Node) xPath.compile("./item[@key='author']")
        .evaluate(bookNode, XPathConstants.NODE);

evaluate использует текущую bookNode в качестве начальной точки.

После этого мы можем проверить все возможные результаты:

  • мы нашли тег key="author" - и он содержит имя автора.
  • мы нашли key="author" тег - но в нем нет имени.
  • нет тега key="author" для этого book узла.
...