Синтаксический анализ XML получение только комментариев и значений даты - PullRequest
0 голосов
/ 14 января 2020

Привет всем, что я пытаюсь увидеть, могу ли я прочитать файл XML и собрать только теги, в которых дата отформатирована как YYYY-MM-DD.

Вот онлайн-пример : https://repl.it/repls/MedicalIgnorantEfficiency

Вот пример моего xml для анализа:

<?xml version="1.0" encoding="UTF-8"?>
<ncc:Message xmlns:ncc="http://blank/1.0.6" 
xmlns:cs="http://blank/1.0.0" 
xmlns:jx="http://blank/1.0.0"
xmlns:jm="http://blank/1.0.0"
xmlns:n-p="http://blank/1.0.0"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://blank/1.0.6/person person.xsd">
    <ncc:DataSection>
        <ncc:PersonResponse>
            <!-- Message -->
            <cs:CText cs:type="No">NO WANT</cs:CText>
            <jm:CaseID>
                <!-- OEA -->
                <jm:ID>ABC123</jm:ID>
            </jm:CaseID>
            <jx:PersonName>
                <!-- NAM -->
                <jx:GivenName>Arugula</jx:GivenName>
                <jx:MiddleName>Pibb</jx:MiddleName>
                <jx:SurName>Atari</jx:SurName>
            </jx:PersonName>
            <!-- DOB -->
            <ncc:PersonBirthDateText>1948-05-11</ncc:PersonBirthDateText>
            <jx:PersonDetails>
                <!-- SXC -->
                <jx:PersonSSN>
                    <jx:ID/>
                </jx:PersonSSN>
            </jx:PersonDetails>
            <n-p:Activity>
                <!--DOZ-->
                <jx:ActivityDate>1996-04-04</jx:ActivityDate>
                <jx:HomeAgency xsi:type="cs:Organization">
                    <!-- ART -->
                    <jx:Organization>
                        <jx:ID>ZR5981034</jx:ID>
                    </jx:Organization>
                </jx:HomeAgency>
            </n-p:Activity>
            <jx:PersonName>
                <!-- DOB Newest -->
                <ncc:BirthDateText>1993-05-12</ncc:BirthDateText>
                <ncc:BirthDateText>1993-05-13</ncc:BirthDateText>
                <ncc:BirthDateText>1993-05-14</ncc:BirthDateText>
                <jx:IDDetails xsi:type="cs:IDDetails">
                    <!-- SMC Checker -->
                    <jx:SSNID>
                        <jx:ID/>
                    </jx:SSNID>
                </jx:IDDetails>
            </jx:PersonName>
        </ncc:PersonResponse>
    </ncc:DataSection>
</ncc:Message>

Я хочу получить значения даты и комментарий 1016 * над этими значениями даты . Так что-то вроде этого для примера xml выше:

Комментарий: <! - DOB -> (n cc: DataSection / n cc: PersonResponse)

Дата: 1948-05-11 (n cc: DataSection / n cc: PersonResponse / n cc: PersonBirthDateText)

.

Комментарий: <! - DOZ -> (n cc: DataSection / n cc: PersonResponse / np: Activity)

Дата: 1996-04-04 (n cc: DataSection / n cc: PersonResponse / np: Activity / jx: ActivityDate)

.

Комментарий: <! - DOB Newest -> (n cc : DataSection / n cc: PersonResponse / jx: PersonName)

Дата:

  1993-05-12 (ncc:DataSection/ncc:PersonResponse/jx:PersonName/ncc:BirthDateText)
  1993-05-13 (ncc:DataSection/ncc:PersonResponse/jx:PersonName/ncc:BirthDateText)
  1993-05-14 (ncc:DataSection/ncc:PersonResponse/jx:PersonName/ncc:BirthDateText)

Код, с которым я пытаюсь это сделать:

public static void xpathNodes() throws ParserConfigurationException, SAXException, IOException, XPathExpressionException {
    File file = new File(base_);
    XPath xPath = XPathFactory.newInstance().newXPath();
    //String expression = "//*[not(*)]";
    String expression = "([0-9]{4})-([0-9]{2})-([0-9]{2})";
    DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
    DocumentBuilder builder = builderFactory.newDocumentBuilder();
    Document document = builder.parse(file);
    document.getDocumentElement().normalize();
    NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);

    for (int i = 0; i < nodeList.getLength(); i++) {
        System.out.println(getXPath(nodeList.item(i)));
    }
}

private static String getXPath(Node node) {
    Node parent = node.getParentNode();

    if (parent == null) {
        return node.getNodeName();
    }

    return getXPath(parent) + "/" + node.getNodeName();
}

public static void main(String[] args) throws Exception {
    xpathNodes();
}

Я знаю, что регулярное выражение (([0-9] {4}) - ([0-9] {2}) - ([0-9] {2})) работает как Я использовал его в Notepad ++ , и он прекрасно работает там, находя даты в открытом файле xml.

В настоящее время я получаю сообщение об ошибке:

Исключение в потоке "основной" javax. xml .transf orm.TransformerException: ожидался путь к месту, но был обнаружен следующий токен: [

Это даже не принимает во внимание комментарии.

Любая помощь будет отличной !

Ответы [ 2 ]

1 голос
/ 14 января 2020

Для выражения XPath 1.0 без RegEx вы вполне могли бы использовать:

//*[string-length()=10]
   [number(substring(.,1,4))=substring(.,1,4)]
   [substring(.,5,1)='-']
   [number(substring(.,6,2))=substring(.,6,2)]
   [substring(.,8,1)='-']
   [number(substring(.,9,2))=substring(.,9,2)]
|
//*[string-length()=10]
   [number(substring(.,1,4))=substring(.,1,4)]
   [substring(.,5,1)='-']
   [number(substring(.,6,2))=substring(.,6,2)]
   [substring(.,8,1)='-']
   [number(substring(.,9,2))=substring(.,9,2)]
   /preceding-sibling::node()[normalize-space()][1][self::comment()]

Обратите внимание: есть некоторое дублированное выражение, потому что вы хотите выбрать элементы и узлы комментариев. В выражении используется хорошо известная идиома для проверки чисел. Наконец, и поскольку нет никакой гарантии в отношении настройки парсера для текстовых узлов, содержащих только пробелы, до использования предиката позиции используется функция normalize-space().

Проверка в здесь

Редактировать : принудительное использование длины строки.

1 голос
/ 14 января 2020

Вы предоставили выражение Regex для API, который ожидает выражение XPath.

Вы можете использовать регулярные выражения с XPath, но вам потребуется процессор, поддерживающий XPath 2.0 или более позднюю версию (например, Saxon). Процессор XPath, поставляемый с JDK, все еще поддерживает только древний стандарт XPath 1.0, который не поддерживает регулярные выражения.

Вы не можете напрямую указать регулярное выражение для xpath.compile(), но вы можете указать выражение XPath для форма //*[matches(., '--my regex--')].

Если вы решите go по саксонскому маршруту, я бы порекомендовал использовать модель внутреннего дерева Саксона, а не DOM, поскольку XPath обычно выполняется в пять-десять раз быстрее, чем DOM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...