2013-05-29 28 views
5

Tôi cần trợ giúp định dạng xml này thành tệp văn bản có chiều rộng cố định bằng cách sử dụng biểu định kiểu xsl. Tôi biết rất ít về xsl và đã tìm thấy rất ít thông tin trực tuyến về cách thực hiện điều này.XML tới tệp văn bản có chiều rộng cố định với tờ kiểu xsl

Về cơ bản tôi cần xml này

<?xml version="1.0" encoding="UTF-8"?> 
<Report> 
    <table1> 
     <Detail_Collection> 
     <Detail> 
      <SSN>*********</SSN> 
      <DOB>1980/11/11</DOB> 
      <LastName>user</LastName> 
      <FirstName>test</FirstName> 
      <Date>2013/02/26</Date> 
      <Time>14233325</Time> 
      <CurrentStreetAddress1>53 MAIN STREET</CurrentStreetAddress1> 
      <CurrentCity>san diego</CurrentCity> 
      <CurrentState>CA</CurrentState> 
     </Detail_Collection> 
    </table1> 
</Report> 

Trong định dạng này, tất cả trên cùng một dòng

*********19801111user   test  201302261423332553 MAIN STREET         san diego   CA 

Đây là độ rộng cố định

FR TO 
1 9  SSN 
10 17 DOB 
18 33 LastName 
34 46 FirstName 
47 54 Date 
55 62 Time 
63 90 CurrentStreetAddress1 
91 115 CurrentCity 
116 131 CurrentStat 

Tất cả giúp đỡ được nhiều đánh giá cao! Cảm ơn bạn trước!

+0

Bạn có thể sử dụng tiện ích mở rộng như nút-set() hoặc tài liệu/tệp xml phụ để giữ chiều rộng và thứ tự của đầu ra không? –

Trả lời

5

Bí quyết để thực hiện điều này trong XSLT 1.0 là nhận ra rằng bạn có thể kết hợp "chiến lược đệm" với "chiến lược chuỗi con" cho một trong hai hoặc cắt một đoạn văn bản thành chiều rộng mong muốn. Đặc biệt, hướng dẫn XSLT của mẫu này:

substring(concat('value to pad or cut', '  '), 1, 5) 

... nơi concat được sử dụng để thêm một số ký tự đệm để một chuỗi và substring được sử dụng để hạn chế chiều rộng tổng thể, rất hữu ích. Như đã nói, đây là giải pháp XSLT 1.0 hoàn thành những gì bạn muốn.

Xin lưu ý rằng trong kết quả mong đợi của bạn, một số chiều rộng ký tự không phù hợp với yêu cầu của bạn; ví dụ, theo yêu cầu, <LastName> phải được kích thước thành 16 ký tự, trong khi đầu ra của bạn dường như cắt nó ở 13. Điều đó nói rằng, tôi tin rằng giải pháp của tôi dưới đây xuất ra những gì bạn mong đợi.

Khi XSLT này:

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"> 
    <xsl:output omit-xml-declaration="no" indent="yes" method="text"/> 
    <xsl:strip-space elements="*"/> 

    <xsl:template match="node()|@*"> 
    <xsl:copy> 
     <xsl:apply-templates select="node()|@*"/> 
    </xsl:copy> 
    </xsl:template> 

    <xsl:template match="Detail"> 
    <xsl:apply-templates /> 
    <xsl:text>&#10;</xsl:text> 
    </xsl:template> 

    <xsl:template match="SSN"> 
    <xsl:value-of 
     select="substring(concat(., '   '), 1, 9)"/> 
    </xsl:template> 

    <xsl:template match="DOB"> 
    <xsl:value-of 
     select="substring(concat(translate(., '/', ''), '  '), 1, 8)"/> 
    </xsl:template> 

    <xsl:template match="LastName"> 
    <xsl:value-of 
     select="substring(concat(., '    '), 1, 16)"/> 
    </xsl:template> 

    <xsl:template match="FirstName"> 
    <xsl:value-of 
     select="substring(concat(., '    '), 1, 13)"/> 
    </xsl:template> 

    <xsl:template match="Date"> 
    <xsl:value-of 
     select="substring(concat(translate(., '/', ''), '  '), 1, 8)"/> 
    </xsl:template> 

    <xsl:template match="Time"> 
    <xsl:value-of 
     select="substring(concat(., ' '), 1, 8)"/> 
    </xsl:template> 

    <xsl:template match="CurrentStreetAddress1"> 
    <xsl:value-of 
     select="substring(concat(., '       '), 1, 28)"/> 
    </xsl:template> 

    <xsl:template match="CurrentCity"> 
    <xsl:value-of 
     select="substring(concat(., '       '), 1, 25)"/> 
    </xsl:template> 

    <xsl:template match="CurrentStat"> 
    <xsl:value-of 
     select="substring(concat(., '    '), 1, 15)"/> 
    </xsl:template> 

</xsl:stylesheet> 

... được điều hành so với XML cung cấp (với một </Detail> thêm để làm cho tài liệu cũng như hình thành):

<Report> 
    <table1> 
    <Detail_Collection> 
     <Detail> 
     <SSN>*********</SSN> 
     <DOB>1980/11/11</DOB> 
     <LastName>user</LastName> 
     <FirstName>test</FirstName> 
     <Date>2013/02/26</Date> 
     <Time>14233325</Time> 
     <CurrentStreetAddress1>53 MAIN STREET</CurrentStreetAddress1> 
     <CurrentCity>san diego</CurrentCity> 
     <CurrentState>CA</CurrentState> 
     </Detail> 
    </Detail_Collection> 
    </table1> 
</Report> 

... kết quả mong muốn được tạo ra:

*********19801111user   test   201302261423332553 MAIN STREET    san diego    CA 
+0

Điều này là hoàn hảo, Cảm ơn bạn. Khi có nhiều phần chi tiết, mỗi phần cho mỗi người, có cách nào để chèn ngắt dòng để mỗi phần chi tiết có nằm trên một dòng mới không? Cảm ơn một lần nữa. – user973671

+0

@ user973671 - câu hỏi hay. Tôi vừa thực hiện một bản cập nhật sẽ chứa đựng kịch bản mà bạn mô tả. – ABach

6

Dưới đây là (theo quan điểm của tôi) LITE đáng tin cậy hơn và phiên bản duy trì:

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

    <xsl:variable name="some_spaces" select="'                 '" /> 

    <xsl:template match="/"> 
     <xsl:apply-templates select="//Detail_Collection/Detail" /> 
    </xsl:template> 

    <xsl:template match="Detail_Collection/Detail"> 
     <xsl:apply-templates mode="format" select="SSN"> 
      <xsl:with-param name="width" select="number(9-1)"/> 
     </xsl:apply-templates> 
     <xsl:apply-templates mode="format_date" select="DOB"> 
      <xsl:with-param name="width" select="number(17-10)"/> 
     </xsl:apply-templates> 
     <xsl:apply-templates mode="format" select="LastName"> 
      <xsl:with-param name="width" select="number(33-18)"/> 
     </xsl:apply-templates> 
     <xsl:apply-templates mode="format" select="FirstName"> 
      <xsl:with-param name="width" select="number(46-34)"/> 
     </xsl:apply-templates> 
     <xsl:apply-templates mode="format_date" select="Date"> 
      <xsl:with-param name="width" select="number(54-47)"/> 
     </xsl:apply-templates> 
     <xsl:apply-templates mode="format" select="Time"> 
      <xsl:with-param name="width" select="number(62-55)"/> 
     </xsl:apply-templates> 
     <xsl:apply-templates mode="format" select="CurrentStreetAddress1"> 
      <xsl:with-param name="width" select="number(90-63)"/> 
     </xsl:apply-templates> 
     <xsl:apply-templates mode="format" select="CurrentCity"> 
      <xsl:with-param name="width" select="number(115-91)"/> 
     </xsl:apply-templates> 
     <xsl:apply-templates mode="format" select="CurrentState"> 
      <xsl:with-param name="width" select="number(131-116)"/> 
     </xsl:apply-templates> 
     <xsl:text>&#10;</xsl:text> 
    </xsl:template> 

    <xsl:template match="node()" mode ="format"> 
     <xsl:param name="width" /> 
     <xsl:value-of select="substring(concat(text(),$some_spaces), 1, $width+1)"/> 
    </xsl:template> 
    <xsl:template match="node()" mode="format_date"> 
     <xsl:param name="width" /> 
     <xsl:value-of select="substring(concat(translate(text(),'/',''),$some_spaces), 1, $width+1)"/> 
    </xsl:template> 

</xsl:stylesheet> 

Nó sẽ tạo ra kết quả đúng ngay cả khi các trường trong đầu vào không theo thứ tự với sản lượng yêu cầu, hoặc nếu trường này bị thiếu trong đầu vào. Ngoài ra, nó cũng cho rằng có nhiều mục nhập Chi tiết.

+0

+1 cho tham số "chiều rộng" tuyệt vời. – ABach

+0

Um, tất cả chiều rộng bị tắt bởi một: nếu CurrentStreet chiếm các cột từ 63 đến 90, chiều rộng của nó là 28, không phải là 90 - 63 (= 27). Và tương tự cho tất cả những người khác. –

+1

@ C.M.Sperberg-McQueen: Với một cái nhìn gần hơn, bạn sẽ tìm thấy ', $ width + 1'. ;-) Trong máy tính nghĩ là tốt hơn trong tính toán hơn so với con người. –

2

Để lồng chuỗi vào một độ dài nhất định trong XSLT 1.0, tôi sẽ sử dụng kết hợp concat() và chuỗi con(). Trong một khuôn mẫu để chi tiết, ví dụ, tôi có thể viết một cái gì đó giống như

<xsl:value-of 
    select="substring(concat(SSN,'   '),1,9)"/> 
<xsl:value-of 
    select="substring(concat(DOB,'   '),1,8)"/> 
<xsl:value-of 
    select="substring(concat(LastName,'    '),1,16)"/> 
... 
<xsl:text>&#xA;</xsl:text> 

Nếu bạn biết rất ít về XSLT, bạn cũng sẽ cần phải học làm thế nào để xây dựng các stylesheet: XSLT thường sử dụng mẫu phù hợp để lái dòng chảy của kiểm soát trong bản định kiểu, thường rất khó cho những người đến từ các ngôn ngữ lập trình bắt buộc để có được đầu của họ xung quanh.

Nếu bạn biết rằng mọi phần tử Chi tiết sẽ có cùng con trong cùng một trình tự (đây là một điều DTD và lược đồ phù hợp), thì điều đơn giản nhất là viết mẫu cho từng loại phần tử có thể xảy ra trong đầu vào. Stylesheet sau minh họa mô hình cho một số nhưng không phải tất cả các yếu tố:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    version="1.0"> 

    <xsl:variable name="blanks10" select="   "/> 
    <xsl:variable name="blanks" 
    select="concat($blanks10, $blanks10, $blanks10)"/> 

    <!--* For Report, table1, and Detail_collection, we just 
     * recur on the children *--> 
    <xsl:template match="Report | table1 | Detail_collection"> 
    <xsl:apply-templates select="*"/> 
    </xsl:template> 

    <!--* For Detail, we recur on the children and supply a 
     * line-ending newline. *--> 
    <xsl:template match="Detail"> 
    <xsl:apply-templates select="*"/> 
    <xsl:text>&#xA;</xsl:text> 
    </xsl:template> 

    <!--* For SSN, DOB, etc., we pad the value with blanks and 
     * truncate at the appropriate length. *--> 
    <xsl:template match="SSN"> 
    <xsl:value-of select="substring(concat(.,$blanks),1,9)" 
    </xsl:template> 

    <!--* For DOB, we assume input is yyyy/mm/dd and output should 
     * be yyyymmdd. *--> 
    <xsl:template match="DOB"> 
    <xsl:value-of 
     select="substring(concat(translate(.,'/',''),$blanks),1,8)" 
    </xsl:template> 

    <xsl:template match="LastName"> 
    <xsl:value-of select="substring(concat(.,$blanks),1,16)" 
    </xsl:template>  

    <!--* FirstName etc. left as exercise for the reader. *--> 

</xsl:stylesheet> 

Nếu chi tiết có thể khác nhau theo thứ tự hoặc dân số, sự thay đổi có thể được bình thường bằng cách thay thế các cuộc gọi đến xsl: apply-templates trong mẫu cho chi tiết với mã như được hiển thị trong đoạn mã đầu tiên ở đây. Đó là phong cách của mã cũng cảm thấy tự nhiên hơn đối với một số lập trình viên thủ tục; vì lý do đó, tôi khuyên bạn nên tránh nó một cách có ý thức trong khi học XSLT. Nếu bạn muốn học XSLT tốt, nó trả tiền để trở thành bạn bè với xsl: apply-templates.

Nếu bạn không quan tâm đến việc học XSLT, thì lời khuyên của tôi là hy vọng rằng ai đó trả lời truy vấn của bạn bằng cách cung cấp cho bạn một giải pháp hoàn chỉnh cho nhiệm vụ của bạn.

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