ru_xml


Extensible Markup Language (XML)

Русскоязычное сообщество


Previous Entry Share Next Entry
XSLT with DTD/XSD
FreeBSD demon
slonopotamus wrote in ru_xml
Имею два xml-файла.

1:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC 
"-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>
</beans>


2:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans">
</beans>


И xslt:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	
	<xsl:output method="text"/>
	<xsl:template match="/">
		<xsl:apply-templates select="beans"/>
	</xsl:template>
	<xsl:template match="beans">
		ЙА ИКСЭСЭЛЬКО!
	</xsl:template>
</xsl:stylesheet>


Вопрос. Почему когда первый документ преобразуется, текст выводится, а во втором - нет? И, соответственно, что надо изменить в xsl, чтобы оно работало с обоими документами?

Задание xmlns="http://www.springframework.org/schema/beans" в xsl не помогает.

UPDATE:
А суть вот в чём. XPath является namespace-aware. Однако для него селектор без нэймспейса селектит только теги, находящиеся вне какого-либа нэймспейса. Какого чёрта оно вообще допускает существование таких тегов - отдельный вопрос.

И на это напоролось уже много народа.

Решений навскидку три:

  • Явно задать префикс для нэймспейса в xsl. Не подходит, если выхотите применять xsl к документам без нэймспеса помимо тех, что с.

  • Селектить без учёта префикса. Чревато селектингом неоттуда в случае документов с многими нэймспесами

  • Иметь два комплекта xsl, одни без нэймспэйсов, другие с. Криво, потому что они будут совершенно идентичны

  • Предварительно процессить xsl, добавляя/удаляя нэймспэйс в зависимости от полученного xml. Монстрообразно, но право на жизнь имеет.


  • 1

все плохо)

(Anonymous)
Задание xmlns="http://www.springframework.org/schema/beans" в xsl не помогает. - это задание не влияет на выборку xpath.
И вообще doctype и namespace разные вещи

Re: все плохо)

Окей, как сделать выборку для дефолтного нэймспейса?

Re: все плохо)

На всякий случай попробовал, потому что иначе вообще говоря xsl не знает к чему привязан дефолтный нэймспейс.

doctype ни при чем, надо понимать что в вариантах 1 и 2 разные тэги beans -- пусто:beans и http://www.springframework.org/schema/beans:beans.

соответственно если в <xsl:stylesheet добавить xpath-default-namespace="http://www.springframework.org/schema/beans", тогда во втором варианте текст будет выводиться, а в первом - нет

если хочется в обоих, тогда надо <xsl:template match="*[local-name()='beans']">.

да, это все в xslt 2.0, не знаю как в предыдущих версиях

ненавижу xslt

*нервно курю в сторонке*

Захерачить xsl'ину через другую xsl'ину, которая в зависимости от будет добавлять xpath-default-namespace? :)

Похоже придётся юзать второй вариант и колбасить селекторы. Мда.

Ну а как ты хочешь? У тебя два совершенно разных элемента, общего в них только local-name(). Так что всё правильно, по нему и надо селектить...

Попробуй b:xmlns="http://www.springframework.org/schema/beans" в xsl и
match="b:beans"

С дефолтными namespaces в xml полная засада.

Такой вариант не подходит, надо, чтобы xsl можно было применять к обоим вариантам документов. Нужен способ сделать выборку по дефолтному нэймспейсу.

Если мое предложение работает, то сделать xsl, который обработает и тот и другой вариант - проще простого.

Со вторым xml оно, конечно, работает. Но тогда не работает с первым. ооо! я понял на что вы намекаете.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:beans="http://www.springframework.org/schema/beans">
	<xsl:template match="beans">
		ЙА ИКСЭСЭЛЬКО!
	</xsl:template>
	<xsl:template match="beans:beans">
		ЙА ИКСЭСЭЛЬКО!
	</xsl:template>
</xsl:stylesheet>


Так?

Ты знал, ты знал :)
Красивее так:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:beans="http://www.springframework.org/schema/beans">
<xsl:template match="beans|beans:beans">
ЙА ИКСЭСЭЛЬКО!
</xsl:template>
</xsl:stylesheet>

Пожалуй да, это красиво :) Большое спасибо

Я бы делал просто двухфазное преобразование. Первое добавляет пространство имен там где его не было. А второе уже собственно делает то что нужно.

  • 1
?

Log in