2013-02-16 4 views
0

Привет У меня ниже образца xml, и мне нужно получить отдельные недействительные письма из XML-документа. я предполагаю, что все элементы времени, как «вложенного исключение составляет: com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 & л» и «: адрес получателя отклонен: неизвестный пользователя в виртуальной таблице псевдонимов;» постояннынужны конкретные значения из xml с XSLT

<?xml version = "1.0" encoding = "UTF-8"?> 
<root> 
    <Error_Message>Error sending mail message. Cause: javax.mail.SendFailedException: Invalid Addresses; 
    nested exception is: 
    com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 &lt;[email protected]>: Recipient address rejected: User unknown in virtual alias table 
; 
    nested exception is: 
    com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 &lt;[email protected]>: Recipient address rejected: User unknown in virtual alias table 
; 
    nested exception is: 
    com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 &lt;[email protected]>: Recipient address rejected: User unknown in virtual alias table 
; 
    nested exception is: 
    com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 &lt;[email protected]>: Recipient address rejected: User unknown in virtual alias table 
; 
    nested exception is: 
    com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 &lt;[email protected]>: Recipient address rejected: User unknown in virtual alias table 
; 
    nested exception is: 
    com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 &lt;[email protected]>: Recipient address rejected: User unknown in virtual alias table 
; 
    nested exception is: 
    com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 &lt;[email protected]>: Recipient address rejected: User unknown in virtual alias table 
    </Error_Message> 
    <err_mesage>5</err_mesage> 
</root> 

Ожидаемый результат:

<root> 
<EMAILID>[email protected]</EMAILID> 
<EMAILID>[email protected]@gmail.com</EMAILID> 
<EMAILID>[email protected]</EMAILID> 
</root> 
+1

Интересное использование для XML-файла. Если вы сами создаете эти XML-файлы, подумайте об их изменении, чтобы они содержали фактические структурированные данные, а не многострочный текст. Если вы не создаете XML, используйте другой инструмент, который лучше подходит для обработки кусков простого текста, то есть языка программирования, отличного от XSLT. – Tomalak

+0

его из исключения JavaEmail, и я должен генерировать недопустимые адреса электронной почты в ожидаемом формате. – user1658369

+1

Можете ли вы хотя бы использовать процессор XSLT 2.0, такой как Saxon 9? В этом случае вы можете попробовать свою удачу с помощью 'xsl: analysis-string'. –

ответ

2

Как говорит Мартин Honnen, анализировать строка является хорошей ставкой здесь. Но формат вашего сообщения настолько прост, что вам не нужно ничего сложнее, чем простые функции манипуляции с строками XSLT 1.0 и рекурсивный именованный шаблон. Вот таблица стилей XSLT 1.0 со встроенными комментариями, чтобы объяснить, что происходит.

Начало таблицы стилей совершенно обычный:

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

    <xsl:output method="xml" indent="yes"/> 

Мы объявляем две переменные для некоторых из постоянного текста в сообщении об ошибке (без особой причины, кроме желания, чтобы не дать эти длинные постоянные строки больше один раз):

<xsl:variable name="prefix" 
       select="' com.sun.mail.smtp.SMTPAddressFailedException: 550 5.1.1 &lt;'"/> 
    <xsl:variable name="suffix" 
       select="'>: Recipient address rejected: User unknown in virtual alias table'"/> 

root элемент размножается:

<xsl:template match="root"> 
    <root> 
     <xsl:apply-templates/> 
    </root> 
    </xsl:template> 

Элемент Error_Message передает свое строковое значение указанному шаблону extract-email-addresses, что делает его название (подробнее см. Ниже).

<xsl:template match="Error_Message"> 
    <xsl:call-template 
     name="extract-email-addresses"> 
     <xsl:with-param name="s" 
         select="string(.)"/> 
    </xsl:call-template> 
    </xsl:template> 

В err_mesage элемент и текстовые узлы подавляются:

<xsl:template match="err_mesage | text()"/> 

extract-email-addresses Шаблон принимает строку в качестве параметра, который по умолчанию пустая строка.

<xsl:template name="extract-email-addresses"> 
    <xsl:param name="s" select="''"/> 

Мы собираемся откусить кусочек строки s в то время, обрабатывать часть мы откусившие, и повторялись на отдыхе. Итак, первое, что мы делаем, это проверить, закончились ли мы. Если $s - пустая строка, ничего не остается делать; мы останавливаем рекурсию и позволяем стеку выскочить.

<xsl:choose> 
     <xsl:when test="$s = ''"> 
     <!--* end of string, we are done. *--> 
     </xsl:when> 

Когда строка не пуста, мы разбиваем строку $s на первой строки, назначая две части к переменным $s1 и $rest:

 <xsl:otherwise> 
     <xsl:variable name="s1" 
      select="substring-before($s,'&#xA;')"/> 
     <xsl:variable name="rest" 
      select="substring-after($s,'&#xA;')"/> 

Сейчас мы ищем различные формы линии могу взять.Большинство линий в сообщении об ошибке является шаблонными игнорироваться:

 <xsl:choose> 
      <xsl:when test="$s1 = 'Error sending mail message. Cause: javax.mail.SendFailedException: Invalid Addresses;'"> 
      <!--* this line is of no 
       * interest, continue *-->  
      </xsl:when> 
      <xsl:when test="$s1 = ' nested exception is:'"> 
      <!--* skip this line *-->  
      </xsl:when> 
      <xsl:when test="$s1 = ';'"> 
      <!--* skip this line *-->  
      </xsl:when> 
      <xsl:when test="$s1 = ''"> 
      <!--* skip this line *-->  
      </xsl:when> 

Когда мы видим строку, начинающиеся с меткой для SMTPAddressFailedException и заканчивая шаблонный об отказе от адреса получателя, мы берем подстроку что происходит после префикса и перед суффиксом, и завернуть его в EMAILID элемент:

  <xsl:when test="starts-with($s1,$prefix) 
          and 
          contains($s1,$suffix)"> 
      <EMAILID> 
       <xsl:value-of select=" 
       substring-before(
        substring-after($s1,$prefix), 
        $suffix) 
       "/> 
      </EMAILID> 
      <xsl:text>&#xA;</xsl:text> 
      </xsl:when> 

Если мы видим любую другую форму линии, то вход не как ожидалось, поэтому мы генерируем диагностическое сообщение и сохранить движение:

  <xsl:otherwise> 
      <xsl:message>Unrecognized line: |<xsl:value-of 
       select="$s1"/>|</xsl:message> 
      </xsl:otherwise> 
     </xsl:choose> 

Что бы мы ни делали первую линию, мы теперь повторялись обрабатывать оставшуюся часть строки в строке:

 <xsl:call-template name="extract-email-addresses"> 
      <xsl:with-param name="s" select="$rest"/> 
     </xsl:call-template> 
     </xsl:otherwise> 
    </xsl:choose> 
    </xsl:template> 

</xsl:stylesheet> 

XSLT инструкция 2,0 проанализируют строки, конечно, будет более компактной, чем это , а регулярные выражения XSLT 2.0 делают гораздо более удобным выполнение сложных задач, чем библиотека XSLT 1.0. (Но если вы знали, как использовать аналитическую строку, вы бы не задали ваш вопрос. Одно из преимуществ меньшей библиотеки и языка в XSLT 1.0 заключается в том, что иногда быстрее решать проблему с 1.0, чем понимать больше сложные конструкции XSLT 2.0 и способы их применения к простой проблеме. Конечно, это общий факт о малых и больших языках.)

Применительно к введенному вами вводу, только что указанная таблица производит почти точный вывод вы показываете:

<?xml version="1.0"?> 
<root><EMAILID>[email protected]</EMAILID> 
<EMAILID>[email protected]</EMAILID> 
<EMAILID>[email protected]</EMAILID> 
<EMAILID>[email protected]</EMAILID> 
<EMAILID>[email protected]</EMAILID> 
<EMAILID>[email protected]</EMAILID> 
<EMAILID>[email protected]</EMAILID> 
</root> 

Он не включает строку для abcdefgh @ gmail.com @ gmail.com; Я предполагаю, что, возможно, это ошибка разреза/вставки в вопросе.

Он также не проверяет, не был ли выслан электронный адрес в данной строке; если это необходимо на практике, я надеюсь, что вам очевидно, как передать второй аргумент, содержащий все электронные адреса, извлеченные до сих пор (с разделителями пробелов или U + A0 или любой символ, который вам нравится, не может появиться в электронном письме адрес) и использовать его для проверки дубликатов перед выпуском элемента EMAILID.

+1

+1 Предложение: используйте комментарии XML и отформатируйте таблицу стилей в ответе как один документ. Это облегчит OP (и другим) копирование таблицы стилей и выполнение и сохранит комментарии в таблице стилей для справки. –

Смежные вопросы