Подтвердить что ты не робот

Как "выбрать" из XML с пространствами имен?

У меня есть документ 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?

4b9b3361

Ответ 1

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

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

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

<xsl:for-each select="//*[local-name()='Row' = and namespace-uri()='urn:schemas-microsoft-com:office:spreadsheet']">
   ...
</xsl:for-each>

Ответ 2

Если вам не интересно пространство имен, вы можете использовать функцию "local-name()" XPath:

<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>

Ответ 3

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

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

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

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

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