2013-02-28 6 views
2

Мне нужно добавить дополнительное пространство имен в XML-файл с уже перенесенным пространством, но только если определенный элемент не существует.Добавить дополнительное пространство имен с XSLT

Мой XML документ выглядит следующим образом:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" company="TestingCorp"> 
    <common>Stuff Here</common> 
    <ns2:person id="123"> 
     <ns3:firstname>Billy</ns3:firstname> 
     <ns2:lastname>Bobby</ns2:lastname> 
    </ns2:person> 
</everyone> 

... и если нет ns3: Firstname элемент в человеке элемент, я хотел бы добавить новое пространство имен и (например, Xmlns: лягушки = "FFF",), а также дополнительный элемент в человеке, как показано ниже:

Желаемый выход:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" xmlns:frog="FFF" company="TestingCorp"> 
    <common>Stuff Here</common> 
    <ns2:person id="123"> 
     <frog:title> 
      <Master/> 
     </frog:title> 
     <ns2:lastname>Bobby</ns2:lastname> 
    </ns2:person> 
</everyone> 

Мой XSL документ в настоящее время является:

<?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" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <xsl:template match="/*"> 
    <xsl:element name="ns:{local-name()}"> 
     <xsl:attribute name="frog">fff</xsl:attribute> 
     <xsl:apply-templates select="node()|@*" /> 
    </xsl:element> 
    </xsl:template> 

</xsl:stylesheet> 

.... к сожалению, это не работает.

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

ответ

2

Сначала вы должны объявить различные пространства имен в таблице стилей, а также пространство имен по "AAA" умолчанию

<?xml version="1.0" encoding="UTF-8"?> 
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns="AAA" 
    xmlns:frog="FFF" 
    xmlns:ns2="BBB" 
    xmlns:ns3="CCC"> 

    <xsl:output method="xml" encoding="UTF-8" indent="yes"/> 
    <xsl:strip-space elements="*"/> 

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

    <!-- for a Person with no firstname, add a frog:title --> 
    <xsl:template match="ns2:person[not(ns3:firstname)]"> 
     <xsl:copy> 
      <!-- must handle attributes before elements/text nodes --> 
      <xsl:apply-templates select="@*" /> 
      <frog:title> 
       <Master/> 
      </frog:title> 
      <xsl:apply-templates select="node()" /> 
     </xsl:copy> 
    </xsl:template> 

</xsl:stylesheet> 

Это произведет

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<everyone xmlns="AAA" xmlns:ns2="BBB" xmlns:ns3="CCC" company="TestingCorp"> 
    <common>Stuff Here</common> 
    <ns2:person id="123"> 
     <frog:title xmlns:frog="FFF"> 
      <Master/> 
     </frog:title> 
     <ns2:lastname>Bobby</ns2:lastname> 
    </ns2:person> 
</everyone> 

Если xmlns:frog абсолютно должен быть на everyone элемента а не на каждом frog:title то вы можете добавить еще один шаблон:

<xsl:template match="/*"> 
    <xsl:copy> 
    <xsl:copy-of select="document('')/xsl:stylesheet/namespace::frog" /> 
    <xsl:apply-templates select="@*|node()" /> 
    </xsl:copy> 
</xsl:template> 

, чтобы скопировать декларацию пространства имен из элемента таблицы стилей (хотя это означало бы, что каждый выходной документ имеет объявление , даже если он не содержит никаких элементов frog:*).


Редактировать: видимо Xalan не любит copy-of пространств имен из document(''), в качестве альтернативы, если вы знаете, что элемент документа всегда будет иметь такое же имя, то вы можете жесткий код, как конечный элемент

<xsl:template match="/*"> 
    <everyone xmlns:frog="FFF"> 
    <xsl:copy-of select="namespace::*" /> 
    <xsl:apply-templates select="@*|node()" /> 
    </everyone> 
</xsl:template> 

(технически это будет делать то, что вы хотите, даже не в этом шаблоне явного xmlns:frog, так как буквальные результат элементы всегда получают объявления пространства имен, которые находятся в области в точке в таблице стилей где они заявлено, но намерение становится яснее, если вы его включите)

This mailing list post дает некоторое представление о причине, по которой document('') не работает должным образом.

+0

Благодарим вас за быстрый ответ. Я еще не проверял это, но из-за очень ограниченного знания XSLT я не вижу, как это добавит только элемент frog: title, если элемент ns3: firstname отсутствует у человека. – user2119994

+0

@ user2119994 трюк находится в 'match =" ns2: person [not (ns3: firstname)] "' - этот шаблон применяется только к элементам 'person', которые не имеют' firstname', те, которые имеют firstname будет использовать шаблон идентификации вместо этого. –

+0

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

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