XPath с использованием выражений с несколькими осями - PullRequest
0 голосов
/ 23 марта 2020

У меня проблемы с пониманием, как использовать оси для сравнения родственных узлов. Я хотел бы выбрать TreeNumbers, у которых есть родительский элемент DescriptorRecord, у которого есть дочерний интерфейс дескриптора, равный элементу-родителю PharmaUI. Я использую XSLT для копирования XML, но добавляю новый элемент PharmaTree для каждого элемента PharmaUI.

XML

<DescriptorRecordSet>
    <DescriptorRecord>
        <DescriptorUI>apple</DescriptorUI>
        <TreeNumberList>
            <TreeNumber>A1</TreeNumber>
        </TreeNumberList>
        <Pharma>
            <PharmaUI>chocolate</PharmaUI>
            <PharmaUI>pear</PharmaUI>
        </Pharma>
    </DescriptorRecord>

    <DescriptorRecord>
        <DescriptorUI>pear</DescriptorUI>
        <TreeNumberList>
            <TreeNumber>B5</TreeNumber>
        </TreeNumberList>
    </DescriptorRecord>

    <DescriptorRecord>
        <DescriptorUI>chocolate</DescriptorUI>
        <TreeNumberList>
            <TreeNumber>C1</TreeNumber>
        </TreeNumberList>
    </DescriptorRecord>
</DescriptorRecordSet>

XSLT

    <xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsd ="http://www.w3.org/2001/XMLSchema#">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:template match="/">    
    <xsl:for-each select="DescriptorRecordSet/DescriptorRecord">
        <DescriptorRecord>
            <DescriptorUI><xsl:value-of select = "DescriptorUI/text()"/></DescriptorUI>
            <Pharma>
                <xsl:for-each select="Pharma/PharmaUI">
                    <PharmaUI><xsl:value-of select = "text()"/></PharmaUI>
                    <PharmaTree>
                        <xsl:value-of select = "//TreeNumber[preceding-sibling::DescriptorUI[text() = ../Pharma/PharmaUI/text()]]/text()"/>
                    </PharmaTree>
                </xsl:for-each>
            </Pharma>
        </DescriptorRecord>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

В настоящее время используемый XPath не работает:

// TreeNumber [previous-sibling :: DescriptorUI [text () = ../Pharma/PharmaUI / text ()]] / text ()

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

    <DescriptorRecord>
        <DescriptorUI>apple</DescriptorUI>
        <TreeNumberList>
            <TreeNumber>A1</TreeNumber>
        </TreeNumberList>
        <Pharma>
            <PharmaUI>chocolate</PharmaUI>
            <PharmaTree>C1</PharmaTree>
            <PharmaUI>pear</PharmaUI>
            <PharmaTree>B5</PharmaTree>
        </Pharma>
    </DescriptorRecord>

Мне бы хотелось, чтобы кто-то объяснил, почему этот XPath не работает и как я могу это исправить, чтобы выбрать правильный элемент, спасибо.

1 Ответ

0 голосов
/ 23 марта 2020

Перекрестные ссылки в XML документах лучше всего обрабатывать в XSLT с помощью ключей:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    version="1.0">

  <xsl:output indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:key name="tree-ref" match="DescriptorRecord/TreeNumberList/TreeNumber" use="../../DescriptorUI"/>

  <xsl:template match="@* | node()">
      <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
      </xsl:copy>
  </xsl:template>

  <xsl:template match="PharmaUI">
      <xsl:copy-of select="."/>
      <ParmaTree>
          <xsl:value-of select="key('tree-ref', .)"/>
      </ParmaTree>
  </xsl:template>

</xsl:stylesheet>

https://xsltfiddle.liberty-development.net/gVhDDyG

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