объединение нескольких инструкций обработки приводит к циклу for в XQuery, XPath

Мне нужно прочитать все инструкции по обработке с NAME="CONTENTTYPE", и я хочу прочитать @VALUE и объединить все значения и вернуться в XQuery/XPath.

Мой XML:

<REG >
    <MARKER MRKEID="SLREG:7.1" MRKTYPE="LD DU" MRKDATE="20130909" MRKTIME="10402688"/>
    <?METADATA NAME="CONTENTTYPE" VALUE="STATUTE"?>
    <?METADATA NAME="CONTENTTYPE" VALUE="LEGISLATIVEDOCUMENT"?>
    <?METADATA NAME="CONTENTTYPE" VALUE="PRIMARYSOURCE"?>
    <?METADATA NAME="SLTAXTYPE" VALUE="PRIMARYSOURCE"?>
</REG>

Ожидаемый результат:

STATUTE
LEGISLATIVEDOCUMENT
PRIMARYSOURCE

Благодарим вас за помощь в написании XQuery/XPath для получения вывода, как указано выше.

Заранее спасибо.

С уважением, Хари


person user2919291    schedule 25.10.2013    source источник
comment
Имя этих инструкций по обработке — METADATA и, например. NAME="CONTENTTYPE" VALUE="STATUTE" — это неструктурированные данные, которые вам нужно будет проанализировать с помощью собственного кода. @VALUE не будет работать, он выбирает атрибут с таким именем, но только узлы элементов имеют атрибуты, а инструкции по обработке - нет.   -  person Martin Honnen    schedule 25.10.2013


Ответы (2)


//processing-instruction('METADATA')[matches(., 'NAME="CONTENTTYPE" VALUE="[^"]*"')]/replace(substring-after(., 'VALUE="'), '"', ''). Это XPath 2.0.

person Martin Honnen    schedule 25.10.2013
comment
Привет, Мартин. Спасибо за ответ, но он возвращает только первое значение, т.е.: УСТАВ. Пожалуйста, дайте мне знать, как я могу получить все три значения. - person user2919291; 25.10.2013
comment
Он должен вернуть последовательность с тремя строковыми значениями для опубликованного вами входного образца. Если вы получаете только одно значение, ваш процессор XPath или API скрывают часть результата. Как вы оцениваете XPath? - person Martin Honnen; 25.10.2013
comment
Привет, Мартин. Пожалуйста, дайте мне знать, можем ли мы получить тот же результат, используя цикл for. - person user2919291; 25.10.2013
comment
@ user2919291, какой API XPath вы используете? - person Martin Honnen; 25.10.2013
comment
Привет Мартин, Мы используем JDOM. - person user2919291; 25.10.2013
comment
@ user2919291, отметьте свой вопрос как jdom и, надеюсь, кто-то другой сможет помочь с использованием этого API. Похоже, что выполнение xpath.diagnose(context, false).getRawResults() вместо xpath.evaluate(context) должно работать, но я не программирую с Java и JDOM, и простое чтение документации по API, вероятно, не лучший способ показать вам работающий код. Так что пометьте свой вопрос как jdom, тогда, надеюсь, кто-то еще может помочь с конкретным кодом для оценки опубликованного XPath с JDOM, чтобы были возвращены все элементы в последовательности строк. - person Martin Honnen; 25.10.2013

Тегирование с помощью JDOM помогло мне найти это.

Приходит длинный ответ ... XPath не имеет встроенной возможности анализировать «стандартный» способ добавления «атрибутов» в ProcessingInstructions. Если вы хотите выполнить объединение значений как часть одного выражения XPath, я думаю, вам не повезло... на самом деле ответ Мартина выглядит многообещающе, но он вернет ряд значений String, а не ProcessingInsructions. JDOM 2.x потребуется Filters.string() в XPath.compile(...), и вы получите результат List<String> для path.evaluate(doc).... Я думаю, что проще сделать это вне XPath. Особенно с учетом того, что поддержка XPath2.0 ограничена при использовании библиотеки Saxon с JDOM 2.x.

Что касается программного обеспечения, то JDOM 2.x очень помогает. Взяв ваш пример XML, я сделал это двумя способами, первый способ использует настраиваемый фильтр в наборе результатов XPath. Второй способ фактически делает то же самое, но ограничивает PI дальше в цикле.

public static void main(String[] args) throws Exception {
    SAXBuilder saxb = new SAXBuilder();
    Document doc = saxb.build(new File("data.xml"));

    // This custom filter will return PI's that have the NAME="CONTENTTYPE" 'pseudo' attribute...
    @SuppressWarnings("serial")
    Filter<ProcessingInstruction> contenttypefilter = new AbstractFilter<ProcessingInstruction>() {

        @Override
        public ProcessingInstruction filter(Object obj) {
            // because we know the XPath expression selects Processing Instructions
            // we can safely cast here:
            ProcessingInstruction pi = (ProcessingInstruction)obj;
            if ("CONTENTTYPE".equals(pi.getPseudoAttributeValue("NAME"))) {
                return pi;
            }
            return null;
        }

    };

    XPathExpression<ProcessingInstruction> xp = XPathFactory.instance().compile(
            // search for all METADATA PI's.
            "//processing-instruction('METADATA')",
            // The XPath will return ProcessingInstruction content, which we
            // refine with our custom filter.
            contenttypefilter);

    StringBuilder sb = new StringBuilder();
    for (ProcessingInstruction pi : xp.evaluate(doc)) {
        sb.append(pi.getPseudoAttributeValue("VALUE")).append("\n");
    }
    System.out.println(sb);
}

Этот второй способ использует более простой и предопределенный Filters.processingInstruction(), но затем выполняет дополнительную фильтрацию вручную....

public static void main(String[] args) throws Exception {
    SAXBuilder saxb = new SAXBuilder();
    Document doc = saxb.build(new File("data.xml"));

    XPathExpression<ProcessingInstruction> xp = XPathFactory.instance().compile(
            // search for all METADATA PI's.
            "//processing-instruction('METADATA')",
            // Use the pre-defined filter to set the generic type
            Filters.processinginstruction());

    StringBuilder sb = new StringBuilder();
    for (ProcessingInstruction pi : xp.evaluate(doc)) {
        if (!"CONTENTTYPE".equals(pi.getPseudoAttributeValue("NAME"))) {
            continue;
        }
        sb.append(pi.getPseudoAttributeValue("VALUE")).append("\n");
    }
    System.out.println(sb);
}
person rolfl    schedule 25.10.2013