2012-06-01 4 views
0

Я пытаюсь написать XSLT для преобразования моего XML из одного формата в другой. Когда я применяю файл .xslt к XML-файлу в VS 2010, , структура вывода XML создается без каких-либо проблем. Но он не заполняет данные, ожидаемые обработкой xsl:value-of.Правильный способ написания xsl: значение в XSLT

Когда я использую XMLSpy и оценить выражение XPath, он говорит no result для выражений в следующих XSLT. Но когда я использую функцию node() в конце выражения XPath, она показывает значение!

  1. Каков правильный способ написания XPath?
  2. node() и text() вид функций, действительно необходимых каждый раз для чтения содержимого элемента (когда у него нет дочерних элементов)? Если нет, то почему XmlSpy тоже не дает результата без этих функций?
  3. Иногда (когда я изменяю значение соответствия шаблона от «/» до «ServiceMessage») при отладке XSLT, VS 2010 переходит к встроенным правилам шаблонов. Почему это так? Как я могу избавиться от встроенных шаблонов в VS 2010?

Для примера я следовал за w3school tutorial. Я новичок в XSLT.

Вот мой XML, который я хочу преобразовать в другой формат XML.

<ServiceMessage xmlns="http://requestservice/requests" xmlns:req="http://requestservice/requests/xmlstds"> 

<TypeOfReq> General </TypeOfReq> 
<Details> 
    <Id> 123456789 </Id> 
    <SenderDetails> 
     <Sender id="345"></Sender> 
    </SenderDetails> 
</Details> 

</ServiceMessage> 

Это мой 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="xml" indent="yes"/> 
    <xsl:template match="/"> 
    <request> 
     <requestType> 
     <xsl:value-of select="ServiceMessage/TypeOfReq" /> 
     </requestType> 
     <Id> 
     <xsl:value-of select="ServiceMessage/Details/Id"/> 
     </Id> 
     <senderId> 
     <xsl:value-of select="ServiceMessage/Details/SenderDetails/Sender/@id"/> 
     </senderId> 
    </request> 

    </xsl:template> 



</xsl:stylesheet> 
+0

Thanks @Filburt. Исправлена ​​опечатка. – Learner

ответ

2

Вы написали правильно XPath с облегченной записью точки зрения. Проблема, с которой вы действительно сталкиваетесь, на самом деле связана с пространствами имен. В вашем XML вы указали пространство имен по умолчанию

<ServiceMessage xmlns="http://requestservice/requests"> 

Это означает, что все дочерние элементы, если не указано иное, принадлежат с этим пространством имен. Тем не менее, в вашем XSLT вообще нет ссылки на это имя, так что XSLT ищет элементы, которые не имеют указанного пространства имен. Это не относится к вашему XML.

Для XSLT 1.0, вам нужно будет объявить пространство имен, например, так:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s="http://requestservice/requests"> 

Вы бы тогда однозначно определить, где он используется для согласования элементов

<xsl:value-of select="s:ServiceMessage/s:TypeOfReq" /> 

Вот полный XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s="http://requestservice/requests"> 
    <xsl:output method="xml" indent="yes"/> 
    <xsl:template match="/"> 
     <request> 
     <requestType> 
      <xsl:value-of select="s:ServiceMessage/s:TypeOfReq"/> 
     </requestType> 
     <Id> 
      <xsl:value-of select="s:ServiceMessage/s:Details/s:Id"/> 
     </Id> 
     <senderId> 
      <xsl:value-of select="s:ServiceMessage/s:Details/s:SenderDetails/s:Sender/@id"/> 
     </senderId> 
     </request> 
    </xsl:template> 
</xsl:stylesheet> 

Применительно к вашему XML, следующий выход

<request xmlns:s="http://requestservice/requests"> 
    <requestType> General </requestType> 
    <Id> 123456789 </Id> 
    <senderId>345</senderId> 
</request> 

Обратите внимание, что выбор буквы «здесь» является чисто произвольным, это может быть что-то действительно.

+0

Удивительный! Это сработало. Я приму это как ответ. Но знаете ли вы, почему XmlSpy не предоставляет результат без функций 'node()' или 'text()'? И почему он правильно оценивает выражение Xpath (в этом случае я использую node()) без пространства имен, указанного в выражении? – Learner

+1

node() будет соответствовать элементам, текстам, комментариям и инструкциям обработки, тогда как text() будет соответствовать только text(). Обычно вы не будете использовать text() с xsl: value-of, потому что эта функция все равно вернет текст узла. Обратите внимание (в XSLT1.0), если вы выполняете xsl: значение-значение, а ваше выражение xpath соответствует нескольким узлам, оно возвращает текст только первого совпадающего ему экземпляра. –

+0

Принимая это как ответ, так как он точно идентифицировал проблему и предоставил решение. Другой вопрос о VS построенном шаблоне отвечает @Filburt. – Learner

0

Чтобы ответить на ваш третий вопрос «Как я могу избавиться от встроенных шаблонов?"

Если вы не задаете шаблон для элемента, происходящего в вашем XML, в вашем случае VS будет применяться стандартный шаблон идентичности, который будет просто скопировать исходный элемент на свой выход.

<xsl:template match="/ | @* | node()"> 
    <xsl:copy> 
     <xsl:apply-templates select="@* | node()"/> 
    </xsl:copy> 
</xsl:template> 

См Microsoft's explanation on built in templates подробности.

(атм я не могу сказать, если это возможно, чтобы выключить это, так как я только VS Express, здесь, которые не предлагают отладку XSLT)

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

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:s="http://requestservice/requests"> 

    <xsl:template match="/"> 
     <xsl:apply-templates /> 
    </xsl:template> 

</xsl:stylesheet> 

следующих, в вашем случае, добавьте шаблон для корневого элемента ServiceMessage

<xsl:template match="s:ServiceMessage"> 
    <!-- usually apply-templates, in your case create new output element(s) --> 
<xsl:template> 
+0

Спасибо @Filburt. Это помогло мне понять проблему, с которой я столкнулся во время отладки в VS 2010. – Learner

+0

>> Если вы не укажете шаблон для элемента, входящего в ваш xml, VS применит шаблон идентификации, который просто скопирует исходный элемент на ваш вывод . << Это неверно. –

+0

@torazaburo Если вы знаете лучше, сообщите нам об этом - иначе мой ответ содержит (сокращенную и упрощенную) версию [собственного определения Microsoft] (http://msdn.microsoft.com/en-us/library/bb552390.aspx) – Filburt

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