Как «выбрать» из XML пространства имен? - PullRequest
12 голосов
/ 12 ноября 2008

У меня есть XML-документ, похожий на :::

<?xml version="1.0" encoding="utf-8"?>
<?mso-application progid="Excel.Sheet"?>
<Workbook xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
          xmlns:o="urn:schemas-microsoft-com:office:office"
          xmlns:x="urn:schemas-microsoft-com:office:excel"
          xmlns="urn:schemas-microsoft-com:office:spreadsheet">
  <Worksheet ss:Name="Worksheet1">
    <Table>
      <Column ss:Width="100"></Column>

      <Row>
        <Cell ss:Index="1" ss:StyleID="headerStyle">
          <Data ss:Type="String">Submitted By</Data>
        </Cell>
      </Row>
      <Row>
        <Cell ss:Index="1" ss:StyleID="alternatingItemStyle">
          <Data ss:Type="String">Value1-0</Data>
        </Cell>
      </Row>
    </Table>
    <AutoFilter xmlns="urn:schemas-microsoft-com:office:excel"
                x:Range="R1C1:R1C5"></AutoFilter>
  </Worksheet>
</Workbook>

Проблема заключается в попытке выбрать строки с помощью

  <xsl:for-each select="//Row">
    <xsl:copy-of select="."/>
  </xsl:for-each>

Это не соответствует. Я удалил все пространство имен, и все работает нормально. Итак, как мне получить 'select' для соответствия Row?

Ответы [ 3 ]

30 голосов
/ 12 ноября 2008

Объявите префикс пространства имен для пространства имен в XSLT, а затем select, используя этот префикс:

<xsl:stylesheet ... xmlns:os="urn:schemas-microsoft-com:office:spreadsheet">
  ...   
  <xsl:for-each select="//os:Row">
    ...
  </xsl:for-each>
  ...
</xsl:stylesheet>

Обычно это приводит к тому, что XPath легко читаются. Однако инструменты XSLT / XPath генерируют следующий эквивалентный код:

<xsl:for-each select="//*[local-name()='Row' = and namespace-uri()='urn:schemas-microsoft-com:office:spreadsheet']">
   ...
</xsl:for-each>
10 голосов
/ 12 ноября 2008

Если вас не волнует пространство имен, вы можете использовать XPath `local-name () ':

<xsl:for-each select="//*[local-name() = 'Row']">
  <xsl:copy-of select="."/>
</xsl:for-each>

В качестве альтернативы то же самое можно выразить так. Я не уверен, является ли это стандартным XPath и поддерживают ли все реализации XPath (ColdFusion делает, так что, вероятно, Java также) Может быть, кто-то знает, соответствует ли это какому-либо стандарту.

<xsl:for-each select="//:Row">
  <xsl:copy-of select="."/>
</xsl:for-each>
7 голосов
/ 12 ноября 2008

Tomalek и ckarras дают хорошие ответы, но я хочу уточнить причины, стоящие за ними.

Элементы, которые вы не сопоставляете, находятся в пространстве имен по умолчанию области, в которой они находятся в документе, то есть они находятся в пространстве имен, объявленном для этой области без префикса (например,

xmlns="urn:schemas-microsoft-com:office:spreadsheet"

на элементе Workbook). Хотя у тэгов нет префикса пространства имен, они находятся в пространстве имен.

Однако XPath требует, чтобы все имена элементов в пространстве имен были указаны с префиксом или чтобы пространство имен было явно указано с помощью namespace-uri() в предикате. Следовательно, вы должны либо использовать функцию local-name() в предикате для сопоставления имени элемента (и также использовать функцию namespace-uri(), если существует опасность столкновения имен в пространствах имен), либо вы должны объявить каждое пространство имен, в котором вы хотите сопоставить элементы в XPath с префиксом и квалифицировать имена элементов с их префиксами пространства имен в выражениях XPath.

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