Sản xuất một dòng mới trong XSLT


198

Tôi muốn tạo một dòng mới cho đầu ra văn bản trong XSLT. Có ý kiến ​​gì không?


11
Tôi nghĩ, đã đến lúc chấp nhận câu trả lời :)
Florjon 28/03/2017

Câu trả lời:


240

Mã XSL sau đây sẽ tạo ra một ký tự dòng mới (nguồn cấp dữ liệu):

<xsl:text>&#xa;</xsl:text>

Để trả lại xe , sử dụng:

<xsl:text>&#xd;</xsl:text>

7
+1: điều này mạnh mẽ hơn so với <xsl:text>cách tiếp cận dòng mới nếu bạn sử dụng bất kỳ thứ gì có thể định dạng lại tệp XSL của bạn và gây rối với khoảng trắng.
Ian Roberts

49

Phương pháp ưa thích của tôi để làm điều này trông giống như:

<xsl:stylesheet>

<xsl:output method='text'/>

<xsl:variable name='newline'><xsl:text>
</xsl:text></xsl:variable>

<!-- note that the layout there is deliberate -->

...

</xsl:stylesheet>

Sau đó, bất cứ khi nào bạn muốn xuất một dòng mới (có thể trong csv), bạn có thể xuất ra một cái gì đó như sau:

<xsl:value-of select="concat(elem1,elem2,elem3,$newline)" />

Tôi đã sử dụng kỹ thuật này khi xuất sql từ đầu vào xml. Trong thực tế, tôi có xu hướng tạo các biến cho dấu phẩy, dấu ngoặc kép và dòng mới.


3
Xin lưu ý rằng câu trả lời của Florjon dưới đây ổn định hơn câu trả lời của tôi.
Nic Gibson

1
Có lẽ đáng để thêm phần khai báo xml:space="preserve"vào xsl:textphần tử để tăng tính ổn định, nhưng tôi đồng ý rằng câu trả lời của @ Florjon có thể an toàn hơn.
Flynn1179

Giải pháp này có nhược điểm là bao gồm bất kỳ vết lõm nào, có thể không được mong muốn.
wmassingham 6/07/2015

47

Bao gồm thuộc tính Phương thức = "văn bản" trên thẻ xsl: output và bao gồm các dòng mới trong nội dung bằng chữ của bạn trong XSL tại các điểm thích hợp. Nếu bạn muốn giữ mã nguồn của XSL gọn gàng, hãy sử dụng thực thể &#10;nơi bạn muốn có một dòng mới.


31

Bạn có thể dùng: <xsl:text>&#10;</xsl:text>

xem ví dụ

<xsl:variable name="module-info">
  <xsl:value-of select="@name" /> = <xsl:value-of select="@rev" />
  <xsl:text>&#10;</xsl:text>
</xsl:variable>

nếu bạn viết điều này trong tập tin, vd

<redirect:write file="temp.prop" append="true">
  <xsl:value-of select="$module-info" />
</redirect:write>

biến này sẽ tạo ra một dòng mới infile như:

commons-dbcp_commons-dbcp = 1.2.2
junit_junit = 4.4
org.easymock_easymock = 2.4

6

IMHO không có nhiều thông tin hơn @Florjon đã đưa ra là cần thiết. Có thể một số chi tiết nhỏ còn lại để hiểu tại sao đôi khi nó không hoạt động.

Trước hết, &#xa(hex) hoặc &#10(dec) bên trong a <xsl:text/>sẽ luôn hoạt động, nhưng bạn có thể không thấy nó.

  1. Không có dòng mới trong đánh dấu HTML. Sử dụng đơn giản <br/>sẽ làm tốt. Nếu không, bạn sẽ thấy một khoảng trắng. Xem nguồn từ trình duyệt sẽ cho bạn biết những gì thực sự đã xảy ra. Tuy nhiên, có những trường hợp bạn mong đợi hành vi này, đặc biệt nếu người tiêu dùng không trực tiếp là trình duyệt. Chẳng hạn, bạn muốn tạo một trang HTML và xem cấu trúc của nó được định dạng độc đáo với các dòng và id trống trước khi phục vụ nó cho trình duyệt.
  2. Hãy nhớ nơi bạn cần sử dụng disable-output-escapingvà nơi bạn không sử dụng . Lấy ví dụ sau đây khi tôi phải tạo xml từ người khác và khai báo DTD của nó từ biểu định kiểu.

Phiên bản đầu tiên thoát các ký tự (mặc định cho xsl: text)

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

    <xsl:template match="/">
        <xsl:text>&lt;!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd"&gt;&#xa;&#xa;&#xd;</xsl:text>
        <xsl:copy>
            <xsl:apply-templates select="*" mode="copy"/>
        </xsl:copy>
    </xsl:template>
    <xsl:template match="@*|node()" mode="copy">
        <xsl:copy>
            <xsl:apply-templates select="@*|node()" mode="copy"/>
        </xsl:copy>
    </xsl:template>

</xsl:stylesheet>

và đây là kết quả:

<?xml version="1.0" encoding="utf-8"?>
&lt;!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd"&gt;

&#13;<Subscriptions>
    <User id="1"/>   
</Subscriptions>

Ok, nó làm những gì chúng ta mong đợi, việc thoát được thực hiện để các ký tự chúng ta sử dụng được hiển thị đúng. Định dạng phần XML bên trong nút gốc được xử lý bởi ident="yes". Nhưng nhìn kỹ hơn, chúng ta thấy rằng ký tự dòng mới &#xakhông được thoát và được dịch như hiện tại, thực hiện một dòng cấp dữ liệu kép! Tôi không có một lời giải thích về điều này, sẽ rất tốt để biết. Bất kỳ ai?

Phiên bản thứ hai không thoát khỏi các nhân vật nên họ sản xuất những gì họ muốn làm. Thay đổi được thực hiện là:

<xsl:text disable-output-escaping="yes">&lt;!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd"&gt;&#xa;&#xa;&#xd;</xsl:text>

và đây là kết quả:

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Subscriptions SYSTEM "Subscriptions.dtd">

<Subscriptions>
    <User id="1"/>   
</Subscriptions>

và điều đó sẽ ổn thôi Cả cr và lf đều được kết xuất đúng.

  1. Đừng quên chúng ta đang nói về nl, không crlf( nl=lf). Nỗ lực đầu tiên của tôi là chỉ sử dụng cr: &#xdvà trong khi xml đầu ra được xác thực bởi DOM đúng cách.

Tôi đã xem một xml bị hỏng:

<?xml version="1.0" encoding="utf-8"?>
<Subscriptions>riptions SYSTEM "Subscriptions.dtd">
    <User id="1"/>   
</Subscriptions>

Trình phân tích cú pháp DOM bỏ qua các ký tự điều khiển nhưng kết xuất lại không. Tôi đã dành khá nhiều thời gian để đập đầu mình trước khi tôi nhận ra rằng tôi thật ngốc khi không nhìn thấy điều này!

Đối với bản ghi, tôi sử dụng một biến bên trong cơ thể với cả CRLF chỉ để đảm bảo 100% nó sẽ hoạt động ở mọi nơi.


4

Tôi đã thêm DOCTYPEchỉ thị mà bạn thấy ở đây:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:stylesheet [
  <!ENTITY nl "&#xa;">
]>
<xsl:stylesheet xmlns:x="http://www.w3.org/2005/02/query-test-XQTSCatalog"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="2.0">

Điều này cho phép tôi sử dụng &nl;thay vì &#xa;tạo ra một dòng mới trong đầu ra. Giống như các giải pháp khác, điều này thường được đặt bên trong một <xsl:text>thẻ.


3

Bạn co thể thử,

<xsl:text>&#xA;</xsl:text>

Nó sẽ làm việc.


2

Tôi thứ hai phương pháp của Nic Gibson, đây luôn là phương pháp yêu thích của tôi:

<xsl:variable name='nl'><xsl:text>
</xsl:text></xsl:variable>

Tuy nhiên, tôi đã sử dụng tác vụ Ant <echoxml> để tạo biểu định kiểu và chạy chúng với các tệp. Tác vụ sẽ thực hiện các mẫu giá trị thuộc tính, ví dụ $ {DSTAMP}, nhưng cũng sẽ định dạng lại xml của bạn, vì vậy trong một số trường hợp, tham chiếu thực thể là thích hợp hơn.

<xsl:variable name='nl'><xsl:text>&#xa;</xsl:text></xsl:variable>

3
Nếu bạn sử dụng một biến, nó sẽ tốt hơn để sử dụng selectthay vì xsl:text. Ví dụ: <xsl:variable name="nl" select="'&#xA;'"/>Bằng cách đó, bạn không tạo RTF không cần thiết (đoạn cây kết quả).
Daniel Haley

2

Tôi đã tìm thấy một sự khác biệt giữa dòng mới <xsl:text>theo nghĩa đen và dòng mới bằng chữ sử dụng &#xA;.

Mặc dù các dòng mới theo nghĩa đen hoạt động tốt trong môi trường của tôi (sử dụng cả bộ xử lý Saxon và bộ xử lý Java XSLT mặc định), mã của tôi không thành công khi nó được thực thi bởi một nhóm khác chạy trong môi trường .NET.

Việc thay đổi thành các thực thể ( &#xA;) có mã tạo tệp của tôi chạy ổn định trên cả Java và .NET.

Ngoài ra, các dòng mới theo nghĩa đen dễ bị định dạng lại bởi các IDE và có thể vô tình bị mất khi tệp được duy trì bởi một người nào đó 'không biết'.


2

Tôi đã nhận thấy từ kinh nghiệm của mình rằng việc tạo ra một dòng mới TRONG một <xsl:variable>mệnh đề không hoạt động. Tôi đã cố gắng làm một cái gì đó như:

<xsl:variable name="myVar">
  <xsl:choose>
    <xsl:when test="@myValue != ''">
      <xsl:text>My value: </xsl:text>
      <xsl:value-of select="@myValue" />
      <xsl:text></xsl:text> <!--NEW LINE-->
      <xsl:text>My other value: </xsl:text>
      <xsl:value-of select="@myOtherValue" />
    </xsl:when>
  </xsl:choose>
<xsl:variable>

<div>
  <xsl:value-of select="$myVar"/>
</div>

Bất cứ điều gì tôi đã cố gắng đưa vào "dòng mới" ( <xsl:text>nút trống ) chỉ không hoạt động (bao gồm hầu hết các đề xuất đơn giản hơn trong trang này), không đề cập đến thực tế là HTML sẽ không hoạt động ở đó, vì vậy cuối cùng tôi phải chia nó thành 2 biến, gọi chúng ngoài <xsl:variable>phạm vi và đặt một đơn giản <br/>giữa chúng, nghĩa là:

<xsl:variable name="myVar1">
  <xsl:choose>
    <xsl:when test="@myValue != ''">
      <xsl:text>My value: </xsl:text>
      <xsl:value-of select="@myValue" />
    </xsl:when>
  </xsl:choose>
<xsl:variable>

<xsl:variable name="myVar2">
  <xsl:choose>
    <xsl:when test="@myValue != ''">
      <xsl:text>My other value: </xsl:text>
      <xsl:value-of select="@myOtherValue" />
    </xsl:when>
  </xsl:choose>
<xsl:variable>

<div>
  <xsl:value-of select="$myVar1"/>
  <br/>
  <xsl:value-of select="$myVar2"/>
</div>

Vâng, tôi biết, đó không phải là giải pháp phức tạp nhất nhưng nó hoạt động, chỉ chia sẻ trải nghiệm thất vọng của tôi với XSL;)


2

Tôi không thể chỉ sử dụng <xsl:text>&#xa;</xsl:text>cách tiếp cận vì nếu tôi định dạng tệp XML bằng XSLT, thực thể sẽ biến mất. Vì vậy, tôi đã phải sử dụng một vòng tròn hơn một chút về cách tiếp cận bằng cách sử dụng các biến

<xsl:variable name="nl" select="'&#10;'"/>
<xsl:template match="/">
    <xsl:value-of select="$nl" disable-output-escaping="no"/>
    <xsl:apply-templates select="*"/>
</xsl:template>

-4

chỉ cần thêm thẻ này:

<br/>

nó làm việc cho tôi;).


7
Câu hỏi là về đầu ra văn bản. Giải pháp của bạn sẽ chỉ hoạt động nếu đầu ra được hiển thị dưới dạng HTML.
oberlies
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.