Разбор xml и удаление атрибута ширины из тега изображения

#javascript #node.js

Вопрос:

Я читаю XML-файл и анализирую его. Я хочу удалить width атрибут из каждого img элемента, который является частью XML-документа.

Как мне проанализировать этот HTML-файл, выполнить поиск тега изображения, обновить его и вернуть обновленный HTML?

Далее следует образец XML..В теге description требуется удалить img attr

        <?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>

  <channel>
<title></title>
<atom:link href="" rel="self" type="application/rss xml" />
<link></link>
<description>Award-Winning Impact Media - Alt Protein amp;#38; 
    Sustainability Breaking News</description>
<lastBuildDate>Sun, 24 Oct 2021 19:27:36  0000</lastBuildDate>
<language>en-US</language>
<sy:updatePeriod>
hourly  </sy:updatePeriod>
<sy:updateFrequency>
1   </sy:updateFrequency>

<item>
    <title>Vegan .</title>
    <link>https://www.google.com</link>
    
    <dc:creator><![CDATA[Sally Ho]]></dc:creator>
    <pubDate>Mon, 25 Oct 2021 00:00:00  0000</pubDate>
            <category><![CDATA[Alt Protein]]></category>
    <category><![CDATA[Seafood]]></category>
    <category><![CDATA[Vegan]]></category>
    <category><![CDATA[alternative seafood]]></category>
    <category><![CDATA[plant based tuna]]></category>
    <category><![CDATA[vegan seafood]]></category>
    <category><![CDATA[vegan tuna]]></category>
    <guid isPermaLink="false">https://www.google.com/?p=55401</guid>

                <description><![CDATA[<div style="margin- 
 bottom:20px;"> 
<img width="1024" height="768" src="" class="attachment-post- 
  thumbnail size-post-thumbnail wp-post-image" alt="" srcset="" 
  sizes=" 
    (max-width: 1024px) 100vw, 1024px" /></div>
     <p><span class="rt-reading-time" style="display: block;"><span 
     class="rt-label rt-prefix"></span> <span class="rt- 
       time">4</span> 
       <span class="rt-label rt-postfix">  Mins Read</span></span> 
      </p>
     <p>The post <a rel="nofollow" 
       href="https://www.greenqueen.com.hk/vegan-tuna-brands/"> <a 
      rel="nofollow" href="">Green</a>.</p>
    ]]></description>
    </item>
 

Комментарии:

1. Вам нужна процедура для возврата текста или объекта, подобного дереву синтаксического анализа? Вам нужно удалять width атрибут из каждого тега изображения? Что представляет собой «тег изображения» — элемент HTML img ?

2. да, вы хотите удалить атрибут width из каждого тега img

3. Из всех тегов изображений?

4. да из всех тегов img

5. Вы непоследовательны — вы говорите о XML или о HTML?

Ответ №1:

getElementsByTagName в этом случае не будет работать, потому что html содержится в разделе CDATA (символьные данные). Содержимое этих разделов не анализируется анализатором XML и не рассматривается как разметка.

См. Ссылку на W3C:

Если они содержат HTML, самый простой способ манипулировать ими в ванильном javascript — это прочитать содержимое из nodeValue свойства и установить его как innerHTML свойство временного элемента, добавляемого к новому DocumentFragment . Это дает вам возможность использовать методы, обычно встречающиеся в document для поиска элементов с использованием селекторов. ( removeWidthFromCDATA функция в приведенном ниже фрагменте).

 const xmlStr = `<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:wfw="http://wellformedweb.org/CommentAPI/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
>

  <channel>
<title></title>
<atom:link href="" rel="self" type="application/rss xml" />
<link></link>
<description>Award-Winning Impact Media - Alt Protein amp;#38; 
    Sustainability Breaking News</description>
<lastBuildDate>Sun, 24 Oct 2021 19:27:36  0000</lastBuildDate>
<language>en-US</language>
<sy:updatePeriod>
hourly  </sy:updatePeriod>
<sy:updateFrequency>
1   </sy:updateFrequency>

<item>
    <title>Vegan .</title>
    <link>https://www.google.com</link>
    
    <dc:creator><![CDATA[Sally Ho]]></dc:creator>
    <pubDate>Mon, 25 Oct 2021 00:00:00  0000</pubDate>
            <category><![CDATA[Alt Protein]]></category>
    <category><![CDATA[Seafood]]></category>
    <category><![CDATA[Vegan]]></category>
    <category><![CDATA[alternative seafood]]></category>
    <category><![CDATA[plant based tuna]]></category>
    <category><![CDATA[vegan seafood]]></category>
    <category><![CDATA[vegan tuna]]></category>
    <guid isPermaLink="false">https://www.google.com/?p=55401</guid>

                <description><![CDATA[<div style="margin- 
 bottom:20px;"> 
<img width="1024" height="768" src="" class="attachment-post- 
  thumbnail size-post-thumbnail wp-post-image" alt="" srcset="" 
  sizes=" 
    (max-width: 1024px) 100vw, 1024px" /></div>
     <p><span class="rt-reading-time" style="display: block;"><span 
     class="rt-label rt-prefix"></span> <span class="rt- 
       time">4</span> 
       <span class="rt-label rt-postfix">  Mins Read</span></span> 
      </p>
     <p>The post <a rel="nofollow" 
       href="https://www.greenqueen.com.hk/vegan-tuna-brands/"> <a 
      rel="nofollow" href="">Green</a>.</p>
    ]]></description>
    </item>
</channel>
</rss>`;

function removeWidthFromCDATA(cdataString) {
    const fragment = document.createDocumentFragment();
    const html = document.createElement("div");
    html.innerHTML = cdataString;
    fragment.appendChild(html);
    
    const images = fragment.querySelectorAll("img");

    for (const image of images)
        if (image.hasAttribute("width"))
            image.removeAttribute("width");

    return html.innerHTML;
}

function cleanRSS(xmlString) {
    const parser = new DOMParser();
    const doc = parser.parseFromString(xmlString, "application/xml");
    const errorNode = doc.querySelector("parsererror");
    if (errorNode) {
        console.error("Error parsing xml string.")
        return false;
    }

    const descs = doc.querySelectorAll("description");
    for (const desc of descs) {
        let content = desc.firstChild;
        if (!content || content.nodeType !== Node.CDATA_SECTION_NODE)
            continue;

        content.nodeValue = removeWidthFromCDATA(content.nodeValue);
    }

    const serializer = new XMLSerializer();
    return serializer.serializeToString(doc);
}

console.log(cleanRSS(xmlStr)); 

В качестве дополнительного примечания: обратите внимание на шаблон, который вы используете для создания RSS-канала. Если у вас есть контроль, вам нужно исправить отсутствующее закрытие <a> тега в конце и обратить внимание на пробелы перед символами новой строки, потому что они прерывают имена классов CSS и свойств, применяемых к элементам внутри раздела CDATA.

Ответ №2:

Если вы можете предоставить образец ввода и вывода, мы можем расширить этот фрагмент и сделать его доступным для выполнения.

 // `xml` is the xml document
const imgs = xml.getElementsByTagName("img");
for (const img of imgs) {
  if (img.hasAttribute("width")) {
    img.removeAttribute("width");
  }
}
// output xml/html string from `xml`
 

Комментарии:

1. Уже пробовал это решение, но не сработало

2. Не возражаете, если опубликуете свои данные и сообщение об ошибке здесь?