Обновление текста на веб-сайте в реальном времени из внешнего XML

#javascript #html #ajax #xml

#javascript #HTML #ajax #xml

Вопрос:

Я внутренний программист, которому поручено создать внешний элемент на сайте.

Мне нужно взять только две точки данных из внешнего XML-файла, а затем обе поместить в существующий HTML-код сайта и обновлять его каждые несколько минут.

Дерево XML большое и имеет несколько родительских элементов, мне нужны только два дочерних элемента из первого родительского элемента «Main-Library»

Вот как выглядит xml. Я сжал его так, чтобы отображался только первый дочерний элемент первых двух родителей:

 <Root>
    <Main-Library>
            <Book>
                <Title>Book Name</Title>
                <Author>John Smith</Author>
                <Genre>Fiction</Genre>
                <Loaned>2020-09-03 13:13:48</Loaned>
                <Price>-13.30</Price>
            </Book>
            .
            .
            .
    </Main-Library>
    <Second-Library>
            <Book>
                <Title>Book Name</Title>
                <Author>John Smith</Author>
                <Genre>Fiction</Genre>
                <Loaned>2020-09-03 13:13:48</Loaned>
                <Price>-13.30</Price>
            </Book>
            .
            .
            .
    </Second-Library>
</Root>
  

Мне нужно взять Loaned и Price из первого родительского элемента Main-Library и поместить их в следующий html:

 <p class="feed">
<span class="feed-text-large">Status: </span>
<span class="price">$35.98</span>
<span class="timestamp">Loaned at 13:13 on September 03, 2020</span>
</p>
  

с ценой и датой, поступающими из XML, и обновляющимися по мере изменения xml.

Буду признателен за любую помощь, которая поможет мне начать работу над этим. Спасибо!

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

1. Предполагая, что структура XML никогда не меняется, вы могли попробовать использовать файл XSLT с небольшим количеством JavaScript для обновления страницы время от времени.

2. «обновление по мере изменения xml» будет непростой задачей; вам придется опросить файл и посмотреть, изменился ли он. Использование ETags поможет смягчить это, но это целая тема сама по себе….

3. Я снова открыл это, потому что вопрос, указанный как дубликат, не включает требование периодического обновления, которое, я думаю, является ключом к выбору правильного подхода.

4. @MichaelKay Повторное открытие вопроса с использованием вашего золотого значка для вопроса, на который у вас есть ответ, выходит за рамки приличия… Не говоря уже о продвижении продукта вашей компании при этом.

5. Боюсь, я не обращаю внимания на значки и тому подобное, я не знал, что для этого нужны какие-либо особые привилегии. Я просто почувствовал, что его закрытие было ошибкой, потому что в вопросе был ключевой аспект, которого не было в приведенном дубликате. Что касается того, что это мой продукт, я отвечаю на вопросы решением, которое я бы использовал, если бы у меня была проблема, независимо от того, мой это продукт или нет, в надежде, что OP сочтет это информативным.

Ответ №1:

Прежде всего — возможно ли использовать JSON? Если да, сделайте это и покажите, как данные выглядят в JSON.

Шаги, которые нужно сделать:

  1. Создайте функцию, которая будет извлекать данные
 function getData() {
  return fetch(theUrl).then(response => response.text())
}
  
  1. Создайте функцию, которая будет анализировать данные
 function parseData(str) {
  const data = (new window.DOMParser()).parseFromString(str, 'text/xml')
  // never did anything with XML so this might be wrong
  // that's why JSON would be A LOT EASIER
  // this should get the first Book
  const Book = data.querySelector('Root Main-Library Book')
  const price = Book.querySelector('Price').innerHTML
  const loaned = Book.querySelector('Loaned').innerHTML
  return { price, loaned }
}
  
  1. Распечатайте данные
 function printData(data) {
  const priceTarget = document.querySelector('.price')
  const loanedTarget = document.querySelector('.timestamp')
  priceTarget.innerHTML = data.price
  loanedTarget = data.loaned
}
  
  1. Создайте функцию, которая будет запускаться периодически
 function update() {
  getData().then(parseData).then(printData)
}
  
  1. Запустите функцию один раз и установите интервал
 const minutes = 5
update()
setInterval(update, minutes * 60 * 1000) // interval in ms, so 60*1000 gets us a minute
  

Я не уверен на 100%, что это сработает — моя главная проблема в том parseData() , потому что я никогда ничего не делал с XML в JavaScript.

РЕДАКТИРОВАТЬ: этот код будет считывать данные из первого элемента Book. Если вы хотите перечислить все книги, код должен быть другим. Дайте мне знать, я отвечу вам примерно через 8 часов, если никто не будет быстрее меня. Спокойной ночи

Ответ №2:

С Saxon-JS вы могли бы сделать это, запустив таблицу стилей XSLT 3.0 в следующих строках:

 <xsl:template name="display">
  <xsl:result-document href="#timestamp">
    <xsl:text>Loaned at {/Root/Main-Library/Book/Loaned
                         => translate(' ', 'T')
                         => xs:dateTime()
                         => format-date('[H00].[m00] on [MNn] [D1o], [Y0001]')
                        }</xsl:text>
  </xsl:result-document>
  <xsl:result-document href="#price">
    <xsl:text>${/Root/Main-Library/Book/Price}</xsl:text>
  </xsl:result-document> 
  <ixsl:schedule-action wait="60000">
    <xsl:call-template name="refresh"/>
  </ixsl:schedule-action>
</xsl-template>

<xsl:template name="refresh">
  <ixsl:schedule-action http-request="....">
    <xsl:call-template name="display"/>
  </ixsl:schedule-action>
</xsl-template>
  

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

Отказ от ответственности: Saxon-JS — это продукт моей компании.