2008-11-12 7 views
12

Tôi có một tài liệu gì đó XML như :::Làm thế nào để 'chọn' từ XML với các không gian tên?

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

Vấn đề là khi cố gắng chọn Rows với

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

Nó không phải là phù hợp. Tôi loại bỏ tất cả các khoảng cách tên và nó hoạt động tốt. Vì vậy, làm thế nào để có được 'chọn' để phù hợp với hàng?

Trả lời

28

Khai báo một tiền tố namespace cho không gian tên trong XSLT của bạn và sau đó sử dụng tiền tố select rằng:

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

Điều này thường dẫn đến XPath đó là dễ đọc. Tuy nhiên, các công cụ XSLT/XPath tạo ra sau, mã tương đương:

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

Cái sau dường như ngắn gọn hơn. Cảm ơn. –

10

Nếu bạn không quan tâm đến không gian tên, bạn có thể sử dụng XPath 'địa phương-name()' chức năng:

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

Ngoài ra điều tương tự tương tự có thể được biểu diễn như thế này. Tôi không chắc chắn nếu đây là XPath tiêu chuẩn và nếu tất cả các cài đặt XPath hỗ trợ nó (Coldfusion, thì có lẽ Java cũng vậy). Có thể ai đó biết nếu điều này phù hợp với bất kỳ tiêu chuẩn nào.

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

Kiểm tra QName này '*: tên địa phương 'chỉ hợp lệ trong XSLT/XPath 2.0 –

+0

Giải pháp này hơi bẩn, nhưng hiệu quả. Nó giải quyết vấn đề của tôi quá (cố gắng để chọn một nút con không có tên trơn). –

+0

@Kevin Phần nào của nó? Đầu tiên hay thứ hai? – Tomalak

7

Tomalekckarras cho câu trả lời tốt, nhưng tôi muốn làm rõ lý do đằng sau họ.

Các yếu tố bạn không phù hợp là trong không gian tên mặc định về phạm vi, trong đó họ xảy ra trong doc, có nghĩa là, họ đang ở trong không gian tên kê khai phạm vi đó mà không có một tiền tố (ví dụ

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

trên phần tử Workbook). Mặc dù các tên miền thiếu một tiền tố không gian tên, chúng nằm trong một không gian tên.

Tuy nhiên, XPath yêu cầu tất cả tên của các phần tử trong không gian tên phải đủ điều kiện với tiền tố hoặc không gian tên được chỉ định rõ ràng với namespace-uri() trong vị từ. Do đó, bạn phải sử dụng hàm local-name() trong một biến vị ngữ để khớp tên phần tử (và sử dụng hàm namespace-uri() nếu có nguy cơ xung đột tên trên các không gian tên) hoặc bạn phải khai báo mỗi không gian tên mà bạn muốn khớp với các phần tử trong XPath với một tiền tố, và đủ điều kiện các tên phần tử với các tiền tố không gian tên của chúng trong các biểu thức XPath.