تحويل XML إلى نص عادي - كيف يجب أن نتجاهل/التعامل مع بيضاء في XSLT ؟

StackOverflow https://stackoverflow.com/questions/184431

  •  06-07-2019
  •  | 
  •  

سؤال

أحاول تحويل ملف XML إلى العلامات المستخدمة من قبل نينو باستخدام XSLT.يعمل هذا في الواقع إلى حد ما ، ولكن المسافة البادئة في ملف XSL الحصول على إدراجها في النتائج.في هذه اللحظة لدي خيارين:التخلي عن هذا XSLT الشيء تماما ، تجد طريقة أخرى لتحويل من XML إلى نينو العلامات أو حذف حوالي 95% فاصل من ملف XSL ، مما يجعل من قريب-غير قابل للقراءة و صيانة كابوس.

هل هناك طريقة للحفاظ على المسافة البادئة في ملف XSL دون تمرير كل بيضاء على النهائي الوثيقة ؟

الخلفية:أنا المهاجرة وهو autodoc أداة من صفحات HTML ثابتة على نينو ، حتى API التي وضعها الفريق الخادم يمكن أن يكون المزيد من التوثيق من قبل التطبيقات الفريق كلما التطبيقات فريق يعمل في سوء الموثقة رمز.المنطق هو أن يكون قسم من كل صفحة جانبا autodoc أداة ، والسماح تعليقات في أي مكان خارج هذه الكتلة.أنا باستخدام XSLT لأن لدينا بالفعل ملف XSL تحويل من لغة XHTML و أنا على افتراض أنه سيكون أسرع إلى كتابة XSL من لفة بلدي الحل من الصفر.

تحرير:آه, صحيح, أحمق لي, أنا أهملت المسافة البادئة السمة.(ملاحظة أساسية أخرى:أنا جديدة على XSLT.) من ناحية أخرى, لا يزال لديك للتعامل مع أسطر.نينو يستخدم أنابيب التفريق بين أعمدة الجدول ، مما يعني أن جميع البيانات في الجدول يجب أن يكون خط على خط واحد.هل هناك طريقة لقمع أسطر كونه أنتج (أحيانا فقط) لذا يمكن أن تفعل بعض المنطق المعقدة إلى حد ما لكل خلية الجدول في حد للقراءة fasion?

هل كانت مفيدة؟

المحلول

هناك ثلاثة أسباب على غير المرغوب فيها بيضاء في نتيجة تحويل XSLT:

  1. بيضاء أن يأتي من بين العقد في المستند المصدر
  2. بيضاء أن يأتي من داخل العقد في المستند المصدر
  3. بيضاء التي تأتي من الأنماط

انا ذاهب الى الحديث عن كل ثلاثة لأنه يمكن أن يكون من الصعب معرفة أين بيضاء يأتي من لذلك قد تحتاج إلى استخدام عدة استراتيجيات.

لمعالجة الفراغات التي بين العقد في مصدر الوثيقة ، يجب عليك استخدام <xsl:strip-space> أن نزيل أي فاصل يظهر بين عقدتين ، ومن ثم استخدام <xsl:preserve-space> للحفاظ على كبيرة بيضاء التي قد تظهر في غضون المحتوى المختلط.على سبيل المثال, إذا كان لديك مصدر الوثيقة تبدو مثل:

<ul>
  <li>This is an <strong>important</strong> <em>point</em></li>
</ul>

ثم سوف تحتاج إلى تجاهل فاصل بين <ul> و <li> و بين </li> و </ul>, التي ليست كبيرة, ولكن الحفاظ على فاصل بين <strong> و <em> عناصر ، هو كبيرة (وإلا ستحصل على "هذا هو **مهم***نقطة*").للقيام بذلك استخدام

<xsl:strip-space elements="*" />
<xsl:preserve-space elements="li" />

على elements السمة على <xsl:preserve-space> أن قائمة أساسا جميع العناصر في المستند الخاص بك أن يكون المحتوى المختلط.

جانبا:باستخدام <xsl:strip-space> أيضا يقلل من حجم شجرة المصدر في الذاكرة ، ويجعل ورقة الأنماط الخاصة بك أكثر كفاءة ، لذلك هو يستحق القيام به حتى إذا لم يكن لديك بيضاء مشاكل من هذا النوع.

لمعالجة الفراغات التي تظهر ضمن العقد في مصدر الوثيقة ، يجب عليك استخدام normalize-space().على سبيل المثال, إذا كان لديك:

<dt>
  a definition
</dt>

ويمكنك أن تكون على يقين من أن <dt> عنصر لن تعقد أي العناصر التي تريد أن تفعل شيئا, ثم يمكنك القيام به:

<xsl:template match="dt">
  ...
  <xsl:value-of select="normalize-space(.)" />
  ...
</xsl:template>

البائعين الرائدة زائدة بيضاء سيتم تجريده من قيمة <dt> العنصر سوف مجرد الحصول على السلسلة "a definition".

لمعالجة بيضاء قادمة من الأنماط ، والتي ربما تكون واحدة كنت تعاني من, هو عندما يكون لديك نص داخل قالب مثل هذا:

<xsl:template match="name">
  Name:
  <xsl:value-of select="." />
</xsl:template>

الأنماط XSLT يتم تحليلها في نفس الطريقة كما في المصدر الوثائق أنها عملية, لذلك أعلاه XSLT هو تفسير الشجرة التي يحمل <xsl:template> العنصر مع match السمة الأولى التي الطفل عقدة النص والذي الطفل الثاني هو <xsl:value-of> العنصر مع select السمة.نص عقدة البائعين الرائدة زائدة بيضاء (بما في ذلك فواصل الأسطر);لأنه هو النص الحرفي في الأنماط ، فإنه يحصل على نسخ حرفيا إلى نتيجة ، مع كل البائعين الرائدة زائدة بيضاء.

ولكن بعض بيضاء في صفحات الأنماط XSLT على تجريد تلقائيا ، أي تلك التي بين العقد.كنت لا تحصل على خط كسر في النتيجة لأن هناك خط فاصل بين <xsl:value-of> و ختام <xsl:template>.

للحصول فقط على النص الذي تريد في نتيجة استخدام <xsl:text> عنصر مثل هذا:

<xsl:template match="name">
  <xsl:text>Name: </xsl:text>
  <xsl:value-of select="." />
</xsl:template>

XSLT المعالج سوف نتجاهل خط فواصل المسافة البادئة التي تظهر بين العقد و إلا إخراج النص داخل <xsl:text> العنصر.

نصائح أخرى

هل تستخدم البادئة = "لا" في العلامة الإخراج الخاص بك؟

<xsl:output method="text" indent="no" />

وأيضا إذا كنت تستخدم XSL: يمكن استخدام القيمة منكم تعطيل الانتاج-هروب = "نعم" للمساعدة في بعض القضايا المسافات البيضاء

@JeniT الجواب هو عظيم ، أنا فقط أريد أن أشير إلى خدعة لإدارة بيضاء.لست متأكدة إنها أفضل طريقة (أو حتى وسيلة جيدة), ولكن بالنسبة لي كان يعمل في الوقت الراهن.

("s" في الفضاء, "ه" فارغة, "ن" على السطر.)

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xsl:transform [
  <!ENTITY s "<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform'> </xsl:text>" >
  <!ENTITY s2 "<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>  </xsl:text>" >
  <!ENTITY s4 "<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>    </xsl:text>" >
  <!ENTITY s6 "<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>      </xsl:text>" >
  <!ENTITY e "<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform'></xsl:text>" >
  <!ENTITY n "<xsl:text xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>
</xsl:text>" >
]>

<xsl:transform version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xsl:output method="text"/>
<xsl:template match="/">
  &e;Flush left, despite the indentation.&n;
  &e;  This line will be output indented two spaces.&n;

      <!-- the blank lines above/below won't be output -->

  <xsl:for-each select="//foo">
    &e;  Starts with two blanks: <xsl:value-of select="@bar"/>.&n;
    &e;  <xsl:value-of select="@baz"/> The 'e' trick won't work here.&n;
    &s2;<xsl:value-of select="@baz"/> Use s2 instead.&n;
    &s2;    <xsl:value-of select="@abc"/>    <xsl:value-of select="@xyz"/>&n;
    &s2;    <xsl:value-of select="@abc"/>&s;<xsl:value-of select="@xyz"/>&n;
  </xsl:for-each>
</xsl:template>
</xsl:transform>

تطبيق:

<?xml version="1.0" encoding="UTF-8"?>
<foo bar="bar" baz="baz" abc="abc" xyz="xyz"></foo>

النواتج:

Flush left, despite the indentation.
  This line will be output indented two spaces.
  Starts with two blanks: bar.
baz The 'e' trick won't work here.
  baz Use s2 instead.
  abcxyz
  abc xyz

'ه' الخدعة تعمل قبل عقدة النص التي تحتوي على واحد على الأقل غير بيضاء الحرف لأن ذلك يوسع هذا:

<xsl:template match="/">
  <xsl:text></xsl:text>Flush left, despite the indentation.<xsl:text>
</xsl:text>

منذ قواعد تجريد بيضاء أقول بيضاء فقط نص العقد على تجريد السطر الجديد و المسافة البادئة بين <xsl:template> و <xsl:text> الحصول على تجريد (جيد).لأن القوانين تقول نص عقدة واحدة على الأقل بيضاء الحرف هو الحفاظ عليها ، الضمني عقدة النص التي تحتوي على " This line will be output indented two spaces." يبقي الرائدة بيضاء (ولكن أعتقد أن هذا يعتمد أيضا على إعدادات شريط/المحافظة/تطبيع).إن "&n;" في نهاية السطر إدراج سطر جديد ، ولكنه يضمن أيضا أن أي التالية بيضاء هو تجاهلها ، لأنه يظهر بين عقدتين.

المشكلة لدي هي عندما أريد أن خرج بادئة الخط الذي يبدأ مع <xsl:value-of>.في هذه الحالة, "&e;" لن يساعد ، لأن المسافة البادئة بيضاء ليس "تعلق" أي غير الأحرف بيضاء.حتى عن تلك الحالات ، استخدام "&s2;" أو "&s4;", اعتمادا على مقدار المسافة البادئة أريد.

انها قبيحة هاك أنا متأكد لكن على الأقل أنا لم يكن لديك مطول "<xsl:text>"الكلمات المتناثرة بلدي XSLT ، على الأقل أنا لا تزال المسافة البادئة XSLT نفسها حتى أنها مقروءة.أشعر أنني إساءة استخدام XSLT عن شيء لم يتم تصميمه (معالجة النصوص) و هذا هو أفضل ما يمكنني القيام به.


تحرير: ردا على تعليقات هذا هو ما يبدو من دون "وحدات الماكرو":

<xsl:template match="/">
  <xsl:text>Flush left, despite the indentation.</xsl:text>
  <xsl:text>  This line will be output indented two spaces.</xsl:text>
  <xsl:for-each select="//foo">
    <xsl:text>  Starts with two blanks: </xsl:text><xsl:value-of select="@bar"/>.<xsl:text>
</xsl:text>
    <xsl:text>    </xsl:text><xsl:value-of select="@abc"/><xsl:text> </xsl:text><xsl:value-of select="@xyz"/><xsl:text>
</xsl:text>
  </xsl:for-each>
</xsl:template>

وأعتقد أن يجعلها أقل وضوحا لمعرفة المقصود إخراج المسافة البادئة, و انها مسامير المسافة البادئة من XSL نفسها لأن </xsl:text> نهاية العلامات قد تظهر في العمود 1 من ملف XSL (وإلا يمكنك الحصول على غير بيضاء في ملف الإخراج).

وفيما يتعلق تحرير الخاص بك عن خطوط جديدة، يمكنك استخدام هذا القالب ليحل محل متكرر سلسلة واحدة ضمن سلسلة أخرى، ويمكنك استخدامه لفترات السطر:

<xsl:template name="replace.string.section">
  <xsl:param name="in.string"/>
  <xsl:param name="in.characters"/>
  <xsl:param name="out.characters"/>
  <xsl:choose>
    <xsl:when test="contains($in.string,$in.characters)">
      <xsl:value-of select="concat(substring-before($in.string,$in.characters),$out.characters)"/>
      <xsl:call-template name="replace.string.section">
        <xsl:with-param name="in.string" select="substring-after($in.string,$in.characters)"/>
        <xsl:with-param name="in.characters" select="$in.characters"/>
        <xsl:with-param name="out.characters" select="$out.characters"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$in.string"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template> 

واتصل على النحو التالي (هذا المثال استبدال فواصل الأسطر في المتغير $ some.string مع الفضاء):

    <xsl:call-template name="replace.string.section">
        <xsl:with-param name="in.string" select="$some.string"/>
        <xsl:with-param name="in.characters" select="'&#xA;'"/>
        <xsl:with-param name="out.characters" select="' '"/>
    </xsl:call-template>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top