2013-10-12 4 views
2

У меня есть файл XML, который выглядит примерно так:XSL элементы Отвернуть на основе условий

<?xml version="1.0" encoding="UTF-8" standalone="yes"?> 
<Multiple xmlns:ns2="someNs2" xmlns="someGenericNs" xmlns:ns4="someNs4" xmlns:ns3="someNs3"> 
    <Single> 
    <Id>60000</Id> 
    <Type>Activate</Type> 
    <Payload> 
     <ns3:Activation> 
     <ns3:Parent> 
      <ns3:TypeId>113</ns3:TypeId> 
      <ns3:TypeName>TestApplication</ns3:TypeName> 
     </ns3:Parent> 
     <ns3:Children> 
      <ns3:Child> 
      <ns3:Key>someKey</ns3:Key> 
      <ns3:ChildTypeName>BadAppType1</ns3:ChildTypeName> 
      </ns3:Child> 
      <ns3:Child> 
      <ns3:Key>someOtherKey</ns3:Key> 
      <ns3:ChildTypeName>GoodAppType1</ns3:ChildTypeName> 
      </ns3:Child> 
     </ns3:Children> 
     </ns3:Activation> 
    </Payload> 
    </Single> 
</Multiple> 

Что мне нужно сделать, это превратить его в более простой форме, как этот:

<?xml version="1.0" encoding="UTF-8"?> 
<MyNewRootNode xmlns="MyNewNamespace"> 
    <Activation> 
     <ApplicationType>TestApplication</ApplicationType> 
     <ValidChildTypeName>GoodAppType1</ValidChildTypeName> 
     <ValidChildKey>someOtherKey</ValidChildKey> 
    </Activation> 
</MyNewRootNode> 

Исходный XML может содержать несколько дочерних узлов, из которых только один будет иметь действительный узел CildTypeName. Моя проблема в том, что если XML действительно содержит несколько дочерних узлов, то мой XSLT просто возьмет первый и преобразует его в новый формат, даже если он содержит недопустимое имя ChildTypeName.

Итак, подведем итоги: Мне нужно преобразовать свой XML в более простой форме. Чтобы создать эту более простую форму, мне нужно отфильтровать все «дочерние» узлы и найти тот, который содержит , действительный «ChildTypeName» и скопировать значения его «Key» и «ChildTypeName» в новый XML.

У меня также есть предопределенный список допустимых имен ChildTypeNames. Он содержит около 3 имен, и это не изменится в ближайшее время.

Это XSLT я уже добрался до сих пор:

<?xml version="1.0" encoding="iso-8859-1"?> 
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="MyNewNamespace" xmlns:ns3="someNs3" exclude-result-prefixes="ns3"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:variable name="activationNode"> 
     <xsl:text>Activation</xsl:text> 
    </xsl:variable> 
    <xsl:variable name="new-root-node"> 
     <xsl:text>MyNewRootNode</xsl:text> 
    </xsl:variable> 

    <xsl:template match="/*"> 
     <xsl:element name="{$new-root-node}"> 
      <xsl:element name="{$activationNode}"> 
       <xsl:call-template name="TemplateOne"/> 
      </xsl:element> 
     </xsl:element> 
    </xsl:template> 


    <xsl:template name="TemplateOne"> 
     <xsl:element name="ApplicationType"> 
      <xsl:value-of select="//ns3:Activation/ns3:Parent/ns3:TypeName"/> 
     </xsl:element> 
     <xsl:element name="ValidChildTypeName"> 
      <xsl:value-of select="//ns3:Activation/ns3:Children/ns3:Child/ns3:ChildTypeName"/> 
     </xsl:element> 
     <xsl:element name="ValidChildKey"> 
      <xsl:value-of select="//ns3:Activation/ns3:Children/ns3:Child/ns3:Key"/> 
     </xsl:element> 
    </xsl:template> 
</xsl:stylesheet> 

Но это будет захватить первый дочерний узел, он находит в этом случае один с «BadAppType1».

ОБНОВЛЕНИЕ: Достигнуто определенное улучшение. Измененный последнюю часть XSLT для:

<xsl:for-each select="//ns3:Activation/ns3:Children/ns3:Child"> 
      <xsl:if test="ns3:ChildTypeName[text()='GoodAppType1']"> 
       <xsl:element name="ValidChildTypeName"> 
        <xsl:value-of select="ns3:ChildTypeName"/> 
       </xsl:element> 
       <xsl:element name="ValidChildKey"> 
        <xsl:value-of select="ns3:Key"/> 
       </xsl:element> 
      </xsl:if> 
     </xsl:for-each> 

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

ответ

1

Если вы пытаетесь выбрать активации элементов, которые имеют ребенка элемента с ChildTypeName из «GoodAppType1», то, возможно, вы можете использовать сопоставление шаблонов, чтобы выбрать такой элемент, в котором она существует.

<xsl:apply-templates 
    select="//ns3:Activation[ns3:Children/ns3:Child/ns3:ChildTypeName='GoodAppType1']" /> 

Затем в шаблоне, который соответствует этому, вы можете легко вывести ApplicationType

<ApplicationType><xsl:value-of select="ns3:Parent/ns3:TypeName" /></ApplicationType> 

И затем выберите Child элемент с требуемым ChildTypeName

<xsl:apply-templates select="ns3:Children/ns3:Child[ns3:ChildTypeName='GoodAppType1']" /> 

И в пределах шаблона что соответствует Ребенок вы также можете получить Ключ и ChildTypeName.

Попробуйте следующие действия XSLT

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns="MyNewNamespace" xmlns:ns3="someNs3" exclude-result-prefixes="ns3"> 
    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/> 

    <xsl:variable name="activationNode"> 
     <xsl:text>Activation</xsl:text> 
    </xsl:variable> 

    <xsl:variable name="new-root-node"> 
     <xsl:text>MyNewRootNode</xsl:text> 
    </xsl:variable> 

    <xsl:template match="/"> 
     <xsl:element name="{$new-root-node}"> 
     <xsl:apply-templates select="//ns3:Activation[ns3:Children/ns3:Child/ns3:ChildTypeName='GoodAppType1']"/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="ns3:Activation"> 
     <xsl:element name="{$activationNode}"> 
     <ApplicationType> 
      <xsl:value-of select="ns3:Parent/ns3:TypeName"/> 
     </ApplicationType> 
     <xsl:apply-templates select="ns3:Children/ns3:Child[ns3:ChildTypeName='GoodAppType1']"/> 
     </xsl:element> 
    </xsl:template> 

    <xsl:template match="ns3:Child"> 
     <ValidChildTypeName> 
     <xsl:value-of select="ns3:ChildTypeName"/> 
     </ValidChildTypeName> 
     <ValidChildKey> 
     <xsl:value-of select="ns3:Key"/> 
     </ValidChildKey> 
    </xsl:template> 
</xsl:stylesheet> 

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

<MyNewRootNode xmlns="MyNewNamespace"> 
    <Activation> 
    <ApplicationType>TestApplication</ApplicationType> 
    <ValidChildTypeName>GoodAppType1</ValidChildTypeName> 
    <ValidChildKey>someOtherKey</ValidChildKey> 
    </Activation> 
</MyNewRootNode> 
Смежные вопросы