#xml #xslt #spring-mvc
#xml #xslt #spring-mvc
Вопрос:
У меня есть код с выводом XML в виде
<?xml version="1.0" encoding="windows-1252" standalone="yes"?>
<products>
<product>
<name>abc</name>
<id>1</id>
</product>
<product>
<name>klm</name>
<id>2</id>
</product>
</products>
Я хочу, чтобы тот же XML отображался и в следующем формате:
<?xml version="1.0" encoding="windows-1252" standalone="yes"?>
<products>
<product>
<name>
<value>abc</value>
<unit></unit>
</name>
<id>
<value>1</value>
<unit></unit>
</id>
<product>
<name>
<value>klm</value>
<unit></unit>
</name>
<id>
<value>2</value>
<unit></unit>
</id>
</product>
Как я могу это сделать с помощью XSLT?
Я использую среду Spring. XML-теги для продукта являются переменными. Они различаются в зависимости от типа продуктов. Код для генерации XML является
JAXBContext jc;
try {
jc = JAXBContext.newInstance(cla);
Marshaller m;
m = jc.createMarshaller();
m.marshal(obj, out);
} catch (JAXBException e) {
e.printStackTrace();
}
Редактировать:
продукт может иметь атрибут weight, поэтому также будет тег
<weight>10lbs<weight>
Этот параметр будет разбит на
<weight>
<value>10</value>
<unit>lbs</unit>
</weight>
Комментарии:
1. Какие данные входят в
<unit />
тег?2. Имя равно нулю, но имеет значение, если тегом является weight или speed и т.д.
3. Можете ли вы также указать этот случай в своем примере кода?
Ответ №1:
Вот пример таблицы стилей [отредактировано, чтобы отразить новое требование с элементом weight]:
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="products">
<xsl:copy>
<product>
<xsl:apply-templates select="product/*"/>
</product>
</xsl:copy>
</xsl:template>
<xsl:template match="product/*">
<xsl:copy>
<value>
<xsl:value-of select="."/>
</value>
<unit></unit>
</xsl:copy>
</xsl:template>
<xsl:template match="product/weight" priority="3">
<xsl:copy>
<value>
<xsl:value-of select="translate(., 'abcdefghijklmnopqrstuvwxyz', '')"/>
</value>
<unit>
<xsl:value-of select="translate(., '0123456789', '')"/>
</unit>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Когда я применяю это к образцу входных данных
<products>
<product>
<name>abc</name>
<id>1</id>
</product>
<product>
<name>klm</name>
<id>2</id>
</product>
<product>
<name>foo</name>
<id>3</id>
<weight>10lbs</weight>
</product>
</products>
Я получаю
<products>
<product>
<name>
<value>abc</value>
<unit/>
</name>
<id>
<value>1</value>
<unit/>
</id>
<name>
<value>klm</value>
<unit/>
</name>
<id>
<value>2</value>
<unit/>
</id>
<name>
<value>foo</value>
<unit/>
</name>
<id>
<value>3</value>
<unit/>
</id>
<weight>
<value>10</value>
<unit>lbs</unit>
</weight>
</product>
</products>
Основываясь на комментарии Алехандро, я, возможно, неправильно истолковал требуемый результат, и вы не хотите объединять продукты, в этом случае используйте
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:strip-space elements="*"/>
<xsl:output indent="yes"/>
<xsl:template match="@* | node()">
<xsl:copy>
<xsl:apply-templates select="@* | node()"/>
</xsl:copy>
</xsl:template>
<xsl:template match="product/*">
<xsl:copy>
<value>
<xsl:value-of select="."/>
</value>
<unit></unit>
</xsl:copy>
</xsl:template>
<xsl:template match="product/weight" priority="3">
<xsl:copy>
<value>
<xsl:value-of select="translate(., 'abcdefghijklmnopqrstuvwxyz', '')"/>
</value>
<unit>
<xsl:value-of select="translate(., '0123456789', '')"/>
</unit>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
затем вы получаете
<products>
<product>
<name>
<value>abc</value>
<unit/>
</name>
<id>
<value>1</value>
<unit/>
</id>
</product>
<product>
<name>
<value>klm</value>
<unit/>
</name>
<id>
<value>2</value>
<unit/>
</id>
</product>
<product>
<name>
<value>foo</value>
<unit/>
</name>
<id>
<value>3</value>
<unit/>
</id>
<weight>
<value>10</value>
<unit>lbs</unit>
</weight>
</product>
</products>
Комментарии:
1. @Martin Honnen Когда я применяю эту таблицу стилей, все XML-теги теряются, и результатом является xbc 1 klm 2.
2. Фарьял, ты уверен, что входные данные в точности соответствуют опубликованным тобой? Звучит так, как будто вы используете совершенно другой входной документ с опубликованными таблицами стилей, возможно, с элементами в каком-то пространстве имен, которое вы нам не показали.
3. Это именно тот результат, который генерируется кодом:<?xml version=»1.0″ encoding = «UTF-8″ standalone =»yes» ?> <продукт> <категория> Ноутбук</category> <описание>Lenovo ThinkPad X100e 2876 — Athlon Neo MV-40 / 1.6 ГГц — Оперативная память 3 ГБ — Жесткий диск 250 ГБ — Мобильность Radeon HD 3200 — Мобильный широкополосный доступ 3G — Гигабитный Ethernet — WLAN: 802.11b / g / n Bluetooth 2.1 — TPM — Windows 7 Pro — 11.6 » Широкоэкранный TFT 1366 x 768 ( WXGA) — камера</description> <id> 1</id> <язык> Английский</language> <вес> 0 фунтов</weight> <беспроводной>WLAN: 802.11b/ g / n Bluetooth 2.1</беспроводной> </продукт>
4. Ну, в вашем исходном сообщении у вас есть корневой элемент с именем
products
, я не вижу этого в коде в вашем последнем комментарии. Пожалуйста, уточните и отредактируйте свой вопрос, чтобы показать имеющиеся у вас входные данные и желаемый результат.5. @Martin Honnen: Я думаю, что нет необходимости в объединении
product
, это просто ошибка желаемого отступа на выходе.
Ответ №2:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes" indent="yes"/>
<xsl:template match="/products">
<xsl:for-each select="product">
<xsl:element name="product">
<xsl:element name="name">
<xsl:element name="value"><xsl:value-of select="name"/></xsl:element>
<xsl:element name="unit"/>
</xsl:element>
<xsl:element name="id">
<xsl:element name="value"><xsl:value-of select="id"/></xsl:element>
<xsl:element name="unit"/>
</xsl:element>
</xsl:element>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
Комментарии:
1. Вы не должны использовать <xsl:for-each>
2. @conqenator Когда я применяю эту таблицу стилей, все XML-теги теряются, а выводом является xbc 1 klm 2
3. @Faryal: Извините, я не могу протестировать код прямо сейчас. Теперь я это исправил. Смотрите, как я редактирую.
4. @Faryal: вы либо неправильно запускаете таблицу стилей, либо неправильно просматриваете выходные данные.
5. @TOUDIdel «Вам не следует использовать
<xsl:for-each>
«. Это комментарий от кого-то с небольшими знаниями. Небольшие знания — опасная вещь. Инструкция xsl:for-each предназначена для определенной цели. Его использование здесь вполне оправданно. Если бы я должен был критиковать этот код, мой первый комментарий был бы об использовании xsl:element вместо буквальных элементов результата, что является совершенно излишне подробным.