Использование XSL / XPath для сопоставления узлов с любым именем, имеющим данный атрибут и дочерний узел

#xslt #xpath

#xslt #xpath

Вопрос:

Я пытаюсь использовать XPath / XSLT для добавления узла к существующему узлу, который удовлетворяет определенным требованиям:

  • Узел имеет атрибут «id»
  • Узел имеет дочерний узел с именем «Тип», содержащий заданный текст, например, «Идентификатор»

В XML для сопоставления:

   <SomeRandomNode>
    <Type>SomeRandomType</Type>
    <Child>
      <Count type="int32">2</Count>       
      <!-- This node should be matched -->
      <Key id="5">
        <Type>Identifier</Type>
        <SomeValue type="string">Hello</SomeValue>
        <SomeOtherValue type="string">World</SomeOtherValue>
      </Key>
    </Child>
  </SomeRandomNode>
</Project>
  

Мне сложно написать выражение соответствия для этого, моя «лучшая» попытка:

 <xsl:template match="*[@id][.//Typename='Identifier']"> 
  <xsl:copy>
    <xsl:attribute name="id">
      <xsl:value-of select="@id"/>
    </xsl:attribute>

    <!-- Copy nodes -->
    <xsl:copy-of select="Type" />
    <xsl:copy-of select="SomeValue" />
    <xsl:copy-of select="SomeOtherValue" />
    <!-- Add new -->
    <NewValue type="string">This node was added</NewValue>
  </xsl:copy>
</xsl:template>
  

Если я заменю * на nodename, это будет работать нормально, но мне нужно сопоставить узлы с любым именем.

Ответ №1:

* Должно работать нормально. Но вы сопоставляете с элементом, Typename а не Type в вашем примере, поэтому попробуйте это:

 *[@id][Type='Identifier']
  

Или:

 *[@id and (Type='Identifier')]
  

Ответ №2:

Ваше соответствие шаблону ищет Typename элементы-потомки, вы хотите искать Type элементы.

Кроме того, в настоящее время выполняется сопоставление для потомков, но ваш вопрос и логика шаблона ищут дочерние элементы.

Вам следует настроить соответствие вашего шаблона на:

 *[@id][Type='Identifier']