2011-11-08 24 views
5

Giả sử chúng ta có xml đơn giản này ...Nhận nút con đầu lòng trong XSLT sử dụng địa phương-name()

<books> 
    <book> 
     <author/> 
     <title/> 
    </book> 
    <book> 
     <author/> 
     <title/> 
    </book> 
</books> 

Tôi đang sử dụng xpath này để có được các yếu tố của dụ cuốn sách đầu tiên.

//books[1]/* 

Returns

<author/> 
<title/> 

Và đó hoạt động tốt, nhưng tôi phải làm cho nó làm việc sử dụng địa phương-name(). Tôi đã thử sau đây nhưng không ai trong số những công việc ...

//*[local-name()='books']/* 

này trả về lặp lại tác giả và tên các yếu tố, không tốt, tôi chỉ cần họ từ đứa con đầu lòng

//*[local-name()='books'][0]/* 

này không Về cơ bản, tôi muốn tạo tệp CSV, vì vậy dòng đầu tiên trong đầu ra sẽ là tiêu đề liệt kê tên thuộc tính sách theo sau là giá trị dữ liệu tùy ý. Tôi chỉ cần làm cho phần tiêu đề hoạt động.

author,title 
john,The End is Near 
sally,Looking for Answers 
+2

Truy vấn của bạn '// books [1]/*' phải trả về hai phần tử sách, không phải là tác giả và phần tử tiêu đề. Vì vậy, có một số nhầm lẫn ở đâu đó. –

+0

Không, nó chỉ trả về cái đầu tiên với biến Xalan 1.0 XSLT của tôi – raffian

+0

Vâng, đó là điều xấu của tôi trong OP, tôi đang sử dụng [1] dựa trên, thx cho thông tin – user646584

Trả lời

9

Các biểu thức đường dẫn bạn nói tác phẩm cho bạn

//books[1]/* 

tạo ra một danh sách tất cả các nút con của (và chỉ trong trường hợp này) xuất hiện đầu tiên của bất kỳ < sách > nút. Bởi vì, trong dữ liệu của bạn, sự xuất hiện duy nhất của < sách > là cội rễ, nó cũng giống như

/books/* 

trả về hai < cuốn sách > nút, và do đó bạn là sai khi nói rằng nó chỉ có một trả về nút.

Thật khó để biết những gì bạn cần, vì nếu bạn luôn được áp dụng local-name đến nút gốc sau đó bạn không cần phải biết tên của nó và có thể truy cập nó với chỉ /*, do đó bạn sẽ muốn chỉ đơn giản

/*/*[1] 

Tuy nhiên để truy cập nút đứa con đầu lòng của một < sách > nút bất cứ nơi nào trong tài liệu bạn sẽ viết

//*[local-name()='books']/*[1] 

bạn nên cẩn thận để nhốt ngữ cảnh của bạn càng nhiều càng tốt p có thể, khi bắt đầu biểu thức XPath với // sẽ bắt buộc tìm kiếm toàn bộ tài liệu, đó là vô nghĩa và tốn thời gian nếu nút được đề cập luôn ở gốc.

+0

Xem các chỉnh sửa của tôi ở trên bài đăng gốc của anh ấy để biết thêm chi tiết về những gì tôi đang cố gắng hoàn thành, xin lỗi vì thiếu chi tiết bổ sung. Tôi đã thử sử dụng/*/* [1], nó in "tác giả, tựa đề" hai lần, tôi chỉ cần in một lần. – raffian

+0

Điều này làm việc, nhờ – raffian

12

Đây là câu hỏi thường gặp - toán tử XPath [] có mức độ ưu tiên cao hơn (ưu tiên) so với toán tử giả //.

Vì vậy:

//someElemName[1] 

chọn mọi phần tử có tên someElemName đó là đứa con đầu lòng của mẹ - và, tùy thuộc vào tài liệu XML, có thể có nhiều hơn một yếu tố như vậy.

Để thay đổi điều này, bạn phải sử dụng dấu ngoặc vuông.

Sử dụng:

(//*[local-name() = 'book'])[1]/* 

Cũng lưu ý: Trong các vị trí XPath là 1-based, không phải 0-based.

xác minh XSLT dựa trên:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="/"> 
    <xsl:copy-of select= 
    "(//*[local-name() = 'book'])[1]/*"/> 
</xsl:template> 
</xsl:stylesheet> 

khi chuyển đổi này được áp dụng trên các tài liệu XML sau:

<books> 
    <book num="1"> 
     <author num="1"/> 
     <title num="1"/> 
    </book> 
    <book num="2"> 
     <author num="2"/> 
     <title num="2"/> 
    </book> 
</books> 

các nút truy nã được lựa chọn và sao chép vào đầu ra :

<author num="1"/> 
<title num="1"/> 
+0

@RaffiM: Câu trả lời của tôi có hữu ích cho bạn không? –

+0

nó là dành cho tôi, cảm ơn câu trả lời Dimitre – user151496

+0

@ user1916182, Bạn được chào đón. –

0

Tôi phải đáp ứng các mối quan tâm tương tự. Tôi đã giải quyết như sau:

//*[local-name()='MYNODENAME' and position()=X] 

Chúc một ngày tốt đẹp.

Các vấn đề liên quan