Разбор xml с использованием xslt не выполняется при добавлении пространства имен в xml

У меня есть следующий xml-файл:

<DataConfiguration 
  xmlns="http://www.mysite.com/namespace"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.mysite.com/namespace/DataConfiguration.xsd">

  <rule>
    <if>
       ...
    </if>
    <then>
       ...
    </then>
  </rule>

</DataConfiguration>

который я хочу проанализировать, используя следующий xslt:

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:doc="http://www.mysite.com/namespace" 
  exclude-result-prefixes="xsi">

<xsl:output omit-xml-declaration="yes"/>
<xsl:output method="text"/>
<xsl:template match = "/">

<xsl:for-each select="//rule">
  <xsl:for-each select="if/*">
     ...
  </xsl:for-each>
</xsl:for-each>

</xsl:template>
</xsl:stylesheet>

Xslt работает так, как ожидалось, но когда я добавляю атрибут xmlns к верхнему элементу xml, он не может найти элементы xml. Я видел несколько связанных вопросов на этом сайте, но до сих пор не понял, как решить мою конкретную проблему. Я попытался добавить документ: к выбранному, как предлагалось здесь но это не помогло. Может это потому, что я использую //? Есть ли другой способ выполнить эти запросы?

Любое другое предложение, как это решить?


person Tamir    schedule 17.10.2011    source источник


Ответы (1)


Это самый большой FAQ по XPath XSLT. Просто ищите: "XPath default namespace"

Очень кратко:

Изменять:

<xsl:for-each select="//rule">   
  <xsl:for-each select="if/*">   
     ...   
  </xsl:for-each>   
</xsl:for-each> 

To:

<xsl:for-each select="//doc:rule">   
  <xsl:for-each select="doc:if/*">   
     ...   
  </xsl:for-each>   
</xsl:for-each> 

Причина наблюдаемой сбивающей с толку проблемы заключается в том, что в XPath любое имя без префикса считается находящимся в "без пространства имен".

Следовательно, select="//rule" не выбирает какой-либо элемент в документе, который находится в пространстве имен по умолчанию - нет элемента с именем rule, который не находится в пространстве имен.

Вместо этого выражение XPath должно содержать имена с префиксом, и этот префикс должен быть связан с пространством имен по умолчанию - как это сделано в приведенном выше решении.

person Dimitre Novatchev    schedule 17.10.2011
comment
Спасибо за быстрый ответ, работает! Чтобы добавить дополнительную информацию, я заметил, что если у меня есть xpath, содержащий несколько элементов, мне нужно добавить префикс к каждому из них, например: ‹xsl: value-of select = // doc: default / doc: applicationName /› - person Tamir; 17.10.2011
comment
@Tamir: Рад, что мой ответ оказался полезным. Пожалуйста, подумайте о том, чтобы принять его, как того требуют правила SO (просто нажмите на галочку рядом с ответом, который вы хотите принять). - person Dimitre Novatchev; 17.10.2011