Выбор условного значения для повторяющихся узлов

#xslt-2.0

#xslt-2.0

Вопрос:

Я новичок в использовании XSLT и столкнулся с проблемой с одной из моих программ. Я пытался решить эту проблему с помощью своих ограниченных знаний, но безрезультатно. Я пытаюсь обработать XML-файл, чтобы получить только части US. Данные содержат как китайскую, так и американскую части. Данные содержатся в повторяющихся узлах.

Я пробовал условные операторы, чтобы ограничить выбор только для получения идентификатора детали США. Тем не менее, я получаю идентификаторы для всех частей.

Это образец входного файла XML:

 <Part>
            <Part_ID>Comp-97531</Part_ID>
            <Country>US</Country>
    <Identification_Data>
        <Product>Finished</Product>
        <ID>12345678909876</ID>
        <ID_Type>CHN-1</ID_Type>
    <Identification_Data>
    <Identification_Data>
        <Product>Finished</Product>
        <ID>123456789</ID>
        <ID_Type>CHN-2</ID_Type>
    </Identification_Data>
    <Identification_Data>
        <Product>Finished</Product>
        <ID>13579</ID>
        <ID_Type>CHN-3</ID_Type>
    </Identification_Data>
    <Identification_Data>
        <Product>Finished</Product>
        <ID>555555555</ID>
        <ID_Type>USA-1</ID_Type>
    </Identification_Data>
</Part>

    <Part>
            <Part_ID>Comp-95137</Part_ID>
            <Country>US</Country>
    <Identification_Data>
        <Product>Finished</Product>
        <ID>1234567812345</ID>
        <ID_Type>CHN-1</ID_Type>
    <Identification_Data>
    <Identification_Data>
        <Product>Finished</Product>
        <ID>987654321</ID>
        <ID_Type>CHN-2</ID_Type>
    </Identification_Data>
    <Identification_Data>
        <Product>Finished</Product>
        <ID>246810</ID>
        <ID_Type>CHN-3</ID_Type>
    </Identification_Data>
    <Identification_Data>
        <Product>Finished</Product>
        <ID>777777777</ID>
        <ID_Type>USA-1</ID_Type>
    </Identification_Data>
</Part>
  

Это код XSLT, который я пытаюсь:

 <xsl:template match="/">
            <FILE>
        <xsl:for-each select="Part">
            <xsl:call-template name="ProductRecord"/>
        </xsl:for-each>
    </FILE>
</xsl:template>

<xsl:template name="ProductRecord">
        <ID>
      <xsl:choose>
            <xsl:when test="Country = 'US'">
          <xsl:if test="Identification_Data/ID_Type='USA-1'">
            <xsl:value-of select="Identification_Data/ID"/>
          </xsl:if>
        </xsl:when>
      </xsl:choose>
    </ID>
</xsl:template>
  

Требование состоит в том, чтобы получать только детали, изготовленные в США, с ID_TYPE = USA-1 .
Используя код XSLT, я ожидаю только значения для ID_Type = USA-1, которые будут равны 555555555. Однако результат, который я получаю, выглядит следующим образом:

   12345678909876 123456789 13579 555555555.
  

Как я могу ограничить выбор, чтобы показывать только данные, относящиеся к США?
Заранее спасибо за ваш ответ.

Ответ №1:

Прежде чем вы начнете возиться с инструкциями XSLT, вы должны начать понимать XPath как его язык выражений, и там вы могли бы просто выбрать //Part[Country = 'US'] , чтобы выбрать Part элементы, для которых выполняется условие Country = 'US' в предикате [Country = 'US'] .

Затем с выбранными Part элементами в качестве контекстного узла вы можете выбрать Identification_Data[ID_Type = 'USA-1']/ID , чтобы выбрать ID дочерние элементы Identification_Data элементов, для которых выполняется условие ID_Type = 'USA-1' .

Чтобы использовать эти выражения XPath в XSLT, вы можете просто использовать

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:template match="root">
     <xsl:apply-templates select="Part[Country = 'US']"/>
  </xsl:template>

  <xsl:template match="Part">
      <xsl:copy-of select="Identification_Data[ID_Type = 'USA-1']/ID"/>
  </xsl:template>

</xsl:stylesheet>
  

Пример на https://xsltfiddle .liberty-development.net/94rmq6q/1 .

Поэтому нет необходимости в каких-либо xsl:call-template или xsl:choose , достаточно простого выбора XPath и шаблонов сопоставления.

Обратите внимание, что мне пришлось исправить часть вашей разметки ввода, а также ввести контейнер корневых элементов для Part элементов, поскольку обычно ввод XSLT представляет собой правильно сформированный XML-документ, а не последовательность Part или другие элементы-братья и сестры.