Re: [Resharper SDK] Распарсить html сохранённый в xml.
От: zhuravlik26 Германия  
Дата: 17.06.15 13:11
Оценка: 2 (1)
Здравствуйте, ifle, Вы писали:

I>Можно ли как-то связать хмл парсер с html парсером?

I>Есть хмл файлы, которые внутри содержат html блоки. Хотелось бы, что-бы на этом html появились html quick fixes.

Можно создать injected-psi для этих блоков с языком html. Нужно завести свой SolutionComponent, отнаследовав его от IndependentInjectedPsiProvider, и там описать, что вы хотите инжектить html в ноды, удовлетворяющие нужному критерию.
Примером того, как сделать подобное, может служить JsDocInjectedPsiProvider.
[Resharper SDK] Распарсить html сохранённый в xml.
От: ifle  
Дата: 17.06.15 05:29
Оценка:
Можно ли как-то связать хмл парсер с html парсером?
Есть хмл файлы, которые внутри содержат html блоки. Хотелось бы, что-бы на этом html появились html quick fixes.
Отредактировано 17.06.2015 5:29 ifle . Предыдущая версия .
Re[2]: [Resharper SDK] Распарсить html сохранённый в xml.
От: ifle  
Дата: 17.06.15 16:56
Оценка:
Здравствуйте, zhuravlik26, Вы писали:

Z>Можно создать injected-psi для этих блоков с языком html. Нужно завести свой SolutionComponent, отнаследовав его от IndependentInjectedPsiProvider, и там описать, что вы хотите инжектить html в ноды, удовлетворяющие нужному критерию.

Z>Примером того, как сделать подобное, может служить JsDocInjectedPsiProvider.

Спасибо, то что нужно. Что должны делать функции CanBeGeneratedNode, CanBeOriginalNode?
Re[3]: [Resharper SDK] Распарсить html сохранённый в xml.
От: zhuravlik26 Германия  
Дата: 18.06.15 09:15
Оценка:
Здравствуйте, ifle, Вы писали:

I>Здравствуйте, zhuravlik26, Вы писали:


Z>>Можно создать injected-psi для этих блоков с языком html. Нужно завести свой SolutionComponent, отнаследовав его от IndependentInjectedPsiProvider, и там описать, что вы хотите инжектить html в ноды, удовлетворяющие нужному критерию.

Z>>Примером того, как сделать подобное, может служить JsDocInjectedPsiProvider.

I>Спасибо, то что нужно. Что должны делать функции CanBeGeneratedNode, CanBeOriginalNode?


CanBeGeneratedNode возвращает, является ли переданная ему нода нодой верхнего уровня заинжекченного языка. В вашем случае оно должно быть в стиле "return node is IHtmlFile;"

CanBeOriginalNode возвращает, является ли переданная ему нода той нодой, куда вы повесили инжект. В вашем случае это какая-то xml-нода.
Re[4]: [Resharper SDK] Распарсить html сохранённый в xml.
От: ifle  
Дата: 18.06.15 11:04
Оценка:
Здравствуйте, zhuravlik26, Вы писали:

Z>Здравствуйте, ifle, Вы писали:


I>>Здравствуйте, zhuravlik26, Вы писали:


Z>>>Можно создать injected-psi для этих блоков с языком html. Нужно завести свой SolutionComponent, отнаследовав его от IndependentInjectedPsiProvider, и там описать, что вы хотите инжектить html в ноды, удовлетворяющие нужному критерию.

Z>>>Примером того, как сделать подобное, может служить JsDocInjectedPsiProvider.

I>>Спасибо, то что нужно. Что должны делать функции CanBeGeneratedNode, CanBeOriginalNode?


Z>CanBeGeneratedNode возвращает, является ли переданная ему нода нодой верхнего уровня заинжекченного языка. В вашем случае оно должно быть в стиле "return node is IHtmlFile;"


Z>CanBeOriginalNode возвращает, является ли переданная ему нода той нодой, куда вы повесили инжект. В вашем случае это какая-то xml-нода.


Заинжекченный ноде у меня парсится как HTML. Вот только с оффсетами не совсем в порядке.
Вот пример, что получается.
<Table>&lt;TAB|LE CELLSPACIN|(0)G=0 CELLPADDIN=0 CLASS=PDS_COMBO_TABLE&gt;&lt;/TABLE&gt;</Table>


Хайглайнинг промахнулся, должен был пометить CELLSPACING=0.
Дело в том, что html не храниться в одной ноде, он храниться как текст xml тага. т.е текст по частям находиться в коллекции xmlTag.InnerTextTokens.
Также есть дополнительные смещения из-за ескеппинга html.

Приемр моего кода
public override IInjectedNodeContext CreateInjectedNodeContext(IInjectedFileContext fileContext, ITreeNode originalNode)
{
    var xmlTag = (IXmlTag) originalNode;

    var text = xmlTag.InnerValue;
    if (string.IsNullOrEmpty(text))
        return null;

    
    StringBuffer buffer = new StringBuffer(text);
    LanguageService languageService = HtmlLanguage.Instance.LanguageService();
    if (languageService == null)
        return null;

    return CreateInjectedFileAndContext(fileContext, xmlTag, buffer, languageService, 0, text.Length);
}
Re[5]: [Resharper SDK] Распарсить html сохранённый в xml.
От: DragonFire Россия  
Дата: 18.06.15 12:33
Оценка:
Привет!

В вашем случае все не так просто. Скорее всего вам нужно написать еще один лексер =)
Процесс будет выглядеть так:
1) Берем исходную xml ноду
<Table>&lt;TAB|LE CELLSPACIN|(0)G=0 CELLPADDIN=0 CLASS=PDS_COMBO_TABLE&gt;&lt;/TABLE&gt;</Table>
2) В injected psi провайдере переопределяем лексер, который будет лексировать ноды, после его прохода, строка должна выглядеть как-то так:
<TABLE CELLSPACING=0 CELLPADDIN=0 CLASS=PDS_COMBO_TABLE></TABLE>
3) Полученную строку отдаем HTML лексеру/парсеру, с которыми он прекрасно справляется

Теперь про лексер. Пусть у нас есть HtmlLexer : ILexer
Сделаем декоратор над этим лексером MySuperLexer : ILexer, который будум использовать вместо оригинального HtmlLexer в inject psi провайдере
Сам MySuperLexer будет:

1) преобразовывать нашу строку к обычной html строке (выпиливать эскейпинг)
2) по построенной html строке создавать новый лексер и делегировать ему операции Start, Advance и т.д.
3) при запросах TokenStart и TokenEnd он должен отдавать настоящие координаты токена внутри оригинальной строки
Прототип:
 public class MySuperLexer : ILexer
  {
    private readonly IBuffer myOriginalBuffer;
    private readonly RangeTranslator myRangeTranslator;
    private readonly HtmlLexer myHtmlLexer;

    public ClrRegexLexer(IBuffer originalBuffer)
    {
      myOriginalBuffer = originalBuffer;

      var htmlString = HtmlUtil.Parse(originalBuffer, out myRangeTranslator);
      var buffer = new StringBuffer(htmlString);
      myHtmlLexer = new HtmlLexer(buffer);
    }

    public void Start()
    {
      myHtmlLexer.Start();
    }

    public void Advance()
    {
      myHtmlLexer.Advance();
    }

    object ILexer.CurrentPosition
    {
      get { return myHtmlLexer.CurrentPosition; }
      set { myHtmlLexer.CurrentPosition = value; }
    }

    public TokenNodeType TokenType
    {
      get { return myHtmlLexer.TokenType; }
    }

    public int TokenStart
    {
      get
      {
        return myRangeTranslator.GetSourceRange(new TextRange(myHtmlLexer.TokenStart, myHtmlLexer.TokenEnd)).StartOffset;
      }
    }

    public int TokenEnd
    {
      get
      {
        return myRangeTranslator.GetSourceRange(myHtmlLexer.TokenEnd - 1).EndOffset;
      }
    }

    public IBuffer Buffer
    {
      get { return myOriginalBuffer; }
    }
  }


Класс RangeTranslator предназначен для хранения информации о взаимном расположении символов в двух строках.
Метод HtmlUtil.Parse вам предстоит написать, или найти что-то похожее, я затрудняюсь сказать делали мы где-то такое или нет. Наверное делали =)

За образец можете взять ClrRegexLexer и логику из CSharpLiteralWrapper.
Аналогично вы сможете склеивать результирующую строку из кусочком, только нужно правильно ренжи сохранять =)
Если будут какие-то специфичные вопросы, пишите мне в скайп skype.stepanov.ev
Re[6]: [Resharper SDK] Распарсить html сохранённый в xml.
От: ifle  
Дата: 19.06.15 14:21
Оценка:
Здравствуйте, DragonFire, Вы писали:

DF>Класс RangeTranslator предназначен для хранения информации о взаимном расположении символов в двух строках.

DF>Метод HtmlUtil.Parse вам предстоит написать, или найти что-то похожее, я затрудняюсь сказать делали мы где-то такое или нет. Наверное делали =)

DF>За образец можете взять ClrRegexLexer и логику из CSharpLiteralWrapper.

DF>Аналогично вы сможете склеивать результирующую строку из кусочком, только нужно правильно ренжи сохранять =)
DF>Если будут какие-то специфичные вопросы, пишите мне в скайп skype.stepanov.ev

Спасибо за такой развёрнутый ответ и предложение о помощи. Если не получиться постучусь.
В моём случае RangeTranslator ключевое звено, которого мне не хватало. С ним всё становится на свои места.

Создал свой лексер, фабрику лексера, переопределил CreateInjectedFileAndContext функцию в моём PsiProvider — валидация заработала.
Есть 2 проблемы с quick fixes:
1. Html quick fixes ничего не знают про RangeTranslator.
Предположим quick fix добавляет новый html атрибут class="centered", он добавляет его не encoded вместо class=&quot;centered&quot;
   &lt;TABLE class="centered" &gt;&lt;/TABLE&gt;

но это не критично, тупо добавил дополнительный encoding

2. Есть ещё одна проблема с html сохранённым в xml. После вызова Regenerate функции в моём PsiProvider, xml меняется,
но почему-то не перезапускается html анализ.
Предположим есть нода у которой есть 2 хайтлайтинга на cellpadding и cellspecing и 2 quick fixes.
После применения первого фикса,второй хайглайтинг пропадает, только после сохранения, он снова появляется.
  <Table><!CDATA[<table cellpadding=1 cellspasing=0></table>]]></Table>


public override void Regenerate(IndependentInjectedNodeContext nodeContext)
{
    var xmlTag = (IXmlTag)nodeContext.OriginalContextNode;
    var factory =  XmlElementFactory.GetInstance(nodeContext.OriginalContextNode);
    var tagText = string.Format("<dummy><![CDATA[{0}]]></dummy>", XmlUtil.UnescapeXmlString(nodeContext.GeneratedNode.GetText()));
    IXmlTag dummyTag = factory.CreateRootTag(tagText);
    LowLevelModificationUtil.ReplaceChildRange(xmlTag.InnerXml.First(), xmlTag.InnerXml.Last(), dummyTag.InnerXml.ToArray());
}


P.S Не слишком ли накладно для каждого xml нода где есть html создавать свой IHtmlFile?
В принципе у меня файлы не большие и не очень критично, просто интересно.
Отредактировано 22.06.2015 12:28 ifle . Предыдущая версия . Еще …
Отредактировано 22.06.2015 5:49 ifle . Предыдущая версия .
Отредактировано 21.06.2015 19:25 ifle . Предыдущая версия .
Отредактировано 21.06.2015 19:18 ifle . Предыдущая версия .
Отредактировано 21.06.2015 12:10 ifle . Предыдущая версия .
Отредактировано 19.06.2015 19:02 ifle . Предыдущая версия .
Отредактировано 19.06.2015 14:28 ifle . Предыдущая версия .
Re[7]: [Resharper SDK] Распарсить html сохранённый в xml.
От: ifle  
Дата: 30.06.15 07:35
Оценка:
Здравствуйте, ifle, Вы писали:

I>Здравствуйте, DragonFire, Вы писали:


DF>>Если будут какие-то специфичные вопросы, пишите мне в скайп skype.stepanov.ev


I>2. Есть ещё одна проблема с html сохранённым в xml. После вызова Regenerate функции в моём PsiProvider, xml меняется,

I> но почему-то не перезапускается html анализ.
I> Предположим есть нода у которой есть 2 хайтлайтинга на cellpadding и cellspecing и 2 quick fixes.
I> После применения первого фикса,второй хайглайтинг пропадает, только после сохранения, он снова появляется.
I>
I>  <Table><!CDATA[<table cellpadding=1 cellspasing=0></table>]]></Table>
I>


I>
I>public override void Regenerate(IndependentInjectedNodeContext nodeContext)
I>{
I>    var xmlTag = (IXmlTag)nodeContext.OriginalContextNode;
I>    var factory =  XmlElementFactory.GetInstance(nodeContext.OriginalContextNode);
I>    var tagText = string.Format("<dummy><![CDATA[{0}]]></dummy>", XmlUtil.UnescapeXmlString(nodeContext.GeneratedNode.GetText()));
I>    IXmlTag dummyTag = factory.CreateRootTag(tagText);
I>    LowLevelModificationUtil.ReplaceChildRange(xmlTag.InnerXml.First(), xmlTag.InnerXml.Last(), dummyTag.InnerXml.ToArray());
I>}
I>


Связаться с DragonFire у меня не получилось. А проблема осталась
Re[8]: [Resharper SDK] Распарсить html сохранённый в xml.
От: DragonFire Россия  
Дата: 30.06.15 12:06
Оценка:
Здравствуйте, ifle, Вы писали:

I>Здравствуйте, ifle, Вы писали:


I>>Здравствуйте, DragonFire, Вы писали:


DF>>>Если будут какие-то специфичные вопросы, пишите мне в скайп skype.stepanov.ev


I>>2. Есть ещё одна проблема с html сохранённым в xml. После вызова Regenerate функции в моём PsiProvider, xml меняется,

I>> но почему-то не перезапускается html анализ.
I>> Предположим есть нода у которой есть 2 хайтлайтинга на cellpadding и cellspecing и 2 quick fixes.
I>> После применения первого фикса,второй хайглайтинг пропадает, только после сохранения, он снова появляется.
I>>
I>>  <Table><!CDATA[<table cellpadding=1 cellspasing=0></table>]]></Table>
I>>


I>>
I>>public override void Regenerate(IndependentInjectedNodeContext nodeContext)
I>>{
I>>    var xmlTag = (IXmlTag)nodeContext.OriginalContextNode;
I>>    var factory =  XmlElementFactory.GetInstance(nodeContext.OriginalContextNode);
I>>    var tagText = string.Format("<dummy><![CDATA[{0}]]></dummy>", XmlUtil.UnescapeXmlString(nodeContext.GeneratedNode.GetText()));
I>>    IXmlTag dummyTag = factory.CreateRootTag(tagText);
I>>    LowLevelModificationUtil.ReplaceChildRange(xmlTag.InnerXml.First(), xmlTag.InnerXml.Last(), dummyTag.InnerXml.ToArray());
I>>}
I>>


I>Связаться с DragonFire у меня не получилось. А проблема осталась


Привет еще раз. А если потайпить внутри измененной ноды анализ перезапуститься? Надо внимально посмотреть, возможно какие-то кеши не сбрасываются....
Все-таки советую связаться со мной напрямую по скайпу "skype.stepanov.ev" или почте "mail.stepanov.ev@gmail.com", быстрее решим проблемы =)
Re[9]: [Resharper SDK] Распарсить html сохранённый в xml.
От: ifle  
Дата: 05.07.15 11:57
Оценка:
Здравствуйте, DragonFire, Вы писали:

DF>Привет еще раз. А если потайпить внутри измененной ноды анализ перезапуститься? Надо внимально посмотреть, возможно какие-то кеши не сбрасываются....

DF>Все-таки советую связаться со мной напрямую по скайпу "skype.stepanov.ev" или почте "mail.stepanov.ev@gmail.com", быстрее решим проблемы =)

Всё получилось, ещё раз спасибо за помощь здесь и через skype.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.