2013-03-01 3 views
1

Можно ли преобразовать атрибут из "book1chapter2" в "chapter2"?xslt удалить часть атрибута

Например, этот узел:

<a myAttribute="part1chapter2" /> 

Должно быть трансформироваться в

<a myAttribute="chapter2" /> 

Я пробовал:

<xsl:variable name="chapter" select="replace('part1chapter2', 'book1', '')" /> 

Но это приводит к ошибке компиляции:

ERROR: 'Error checking type of the expression 'funcall(replace, [literal-expr(part1chapter2), literal-expr(part1), literal-expr()])'.' 
FATAL ERROR: 'Could not compile stylesheet' 

Я использую XSLT версии 2.0.

раствор без какой-либо библиотеки будет оценить :)

EDIT:

Java-код, скомпилировать и запустить с JAVAC -g TestXslt.java; java TestXslt;

public static void main(String[] args) throws IOException, URISyntaxException, TransformerException { 
    TransformerFactory factory = TransformerFactory.newInstance(); 
    Source xslt = new StreamSource(new File("../transform.xslt")); 
    Transformer transformer = factory.newTransformer(xslt); 

    Source text = new StreamSource(new File("../input.xml")); 
    String r = new String(); 
    StreamResult result = new StreamResult(new File("../output.xml")); 
    transformer.transform(text, result); 
} 

Java версия Javac 1.6.0_27

+0

Что таблицы стилей компилятор вы используете? Возможно, это не совсем совместимо с XSLT 2.0. Посмотрите на [этот вопрос] (http://stackoverflow.com/questions/3067113/xslt-string-replace) для конкретного ответа XSLT 1.0. –

+0

Мне хотелось бы решение XSLT 2.0. – Charles

+0

Добавление upvote, потому что я думаю, что downvotes совершенно необоснованны. –

ответ

6

Я думаю, что вы представляете, что версия версии = "2.0" на вашей таблице стилей автоматически получит вам процессор XSLT 2.0. Это не так, как работает. Получаемый вами процессор определяется тем, что находится в вашем пути к классам, и если вы возьмете процессор JDK по умолчанию, он поддерживает только XSLT 1.0. Спецификация для XSLT 1.0 говорит о том, что если он видит вызов нераспознанной функции, такой как replace(), она должна вызывать ошибку во время выполнения.

Чтобы запустить это под XSLT 2.0, скачайте Saxon и убедитесь, что он находится на вашем пути к классу. В идеале, для надежности, не используйте метод загрузки JAXP, чтобы найти его, но загрузите его явно. Вместо

TransformerFactory factory = TransformerFactory.newInstance(); 

сделать

TransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl(); 
+0

Спасибо, я попробую. – Charles

+1

@charles, чтобы узнать версию XSLT, используйте этот код XSLT: найдите результат в output.xml ' Версия XSLT: XSLT Vendor: URL-адрес поставщика XSLT: ' –

+0

Спасибо, что работает: TransformerFactory factory = new net.sf.saxon.TransformerFactoryImpl (); – Charles

1

Я не совсем уверен в том, что вы пытаетесь изменить содержимое атрибута или имя атрибута.

Если первые параметры функции замены (строка ввода, регулярное выражение, строка замены), вы можете попробовать что-то вроде replace(@attributeToChange, 'book1chaper2', 'book1'). Если последнее, то я думаю, что нужно что-то вроде:

<xsl:attribute name="book1"> 
    <xsl:value-of select="@book1chaper2"/> 
</xsl:attribute> 

EDIT

Это странно, что вы получаете ошибку компилятора, хотя. Если есть проблема с этой функцией в вашем XSLT двигателя, другой подход (если вы меняете содержимое) будет:

<xsl:choose> 
    <xsl:when test="@attributeToChange='book1chaper2'"> 
     <xsl:text>book1</xsl:text> 
    </xsl:when> 
    <xsl:otherwise> 
     <xsl:value-of select="@attributeToChange"/> 
    </xsl:otherwise> 
</xsl:choose> 

ДАЛЕЕ EDIT

Похоже, ваш процессор, возможно, XSLT 1.0:

Error when running XSLT with eclipse

Попробуйте использовать starts-with(@attributeToChange, 'book1') в качестве теста в выборе, когда в противном случае.

+0

Я не могу протестировать test = "@ attributeToChange = 'book1chaper2'", потому что Я не знаю «chaper2». – Charles

+0

Как насчет 'start-with (@attributeToChange, 'book1')'. Я не совсем уверен в ваших условиях. – Giles

+0

Вы уверены, что ваш процессор поддерживает XSLT 2.0? – Giles

0

Вы могли бы просто сделать это:

<xsl:variable name="chapter" select="substring-after('book1chapter2', 'book1', '')" /> 

Но будет значение всегда содержат «book1» в начале? Получаете ли вы значение «book1» из другого места и поэтому всегда будете знать, какую часть удалить?

+0

Да, я уверен, что book1 всегда есть. Я пытаюсь выполнить подстроку, но результаты были следующими: ОШИБКА: «Ошибка проверки типа выражения» funcall (substring-after, [literal-expr (part1chapter2), literal-expr (part1), literal-expr()]). ' – Charles

+0

@charles, тогда проблема не с версией XSLT, она с процессором XSLT .. Coz substring-after() присутствует и в XSLT 1.0, а также ... какая IDE вы используете? если это Eclipse, тогда перейдите на XALAN PE, который использует XSLT 2.0 .. –

+0

Я не использую никаких IDE, я использую возвышенное. Компиляция и запуск выполняются с помощью командной строки. Я отредактирую свой вопрос с помощью java-кода. – Charles

Смежные вопросы