как скопировать или сопоставить только выбранные элементы из XML-ввода с пространством имен, а затем одновременно удалить пространство имен - PullRequest
1 голос
/ 03 октября 2011

Ниже приведен мой ввод XML. Как мне скопировать или сопоставить выбранные элементы, которые я хочу отразить в выводе XML, используя XSL.

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

Я смог сделать это без пространства имен из ввода, выполнив копирование, но когда пространство имен присутствует, код не работает.

Я нашел способ удалить пространство имен, но в сочетании с копией не сработал. Я совершенно не понимаю, как ведет себя XSL.

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

Ввод XML:

<Transaction xmlns="http://www.test.com/rdc.xsd">
    <Transaction>
        <StoreName id="aa">STORE A</StoreName>
        <TransNo>TXN0001</TransNo>
        <RegisterNo>REG001</RegisterNo>
        <Items>
            <Item id="1">
                <ItemID>A001</ItemID>
                <ItemDesc>Keychain</ItemDesc>
            </Item>
            <Item id="2">
                <ItemID>A002</ItemID>
                <ItemDesc>Wallet</ItemDesc>
            </Item>
        </Items>
        <IDONTLIKETHIS_1>
            <STOREXXX>XXX</STOREXXX>
            <TRANSXXX>YYY</TRANSXXX>
        </IDONTLIKETHIS_1>
        <IDONTLIKETHIS_2>
            <STOREXXX>XXX</STOREXXX>
            <TRANSXXX>YYY</TRANSXXX>
        </IDONTLIKETHIS_2>
    </Transaction>
</Transaction>

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

<Transaction>
    <Transaction>
        <StoreName id="aa">STORE A</StoreName>
        <TransNo>TXN0001</TransNo>
        <RegisterNo>REG001</RegisterNo>
        <Items>
            <Item id="1">
                <ItemID>A001</ItemID>
                <ItemDesc>Keychain</ItemDesc>
            </Item>
            <Item id="2">
                <ItemID>A002</ItemID>
                <ItemDesc>Wallet</ItemDesc>
            </Item>
        </Items>
    </Transaction>
</Transaction>

Я пробовал приведенный ниже код, но проблема в том, что мне не хватает второго элемента Transaction, а в корневом элементе присутствует атрибут xmlns:

<xsl:template match="*">
  <xsl:copy-of select="@*"/>
  <xsl:apply-templates/>
</xsl:template>
<xsl:template match="node()[not(self::*)]">
  <xsl:copy-of select="."/>      
</xsl:template>   
<xsl:template match="*">
  <xsl:copy>
      <xsl:copy-of select="x:Transaction/x:StoreName"/>
      <xsl:copy-of select="x:Transaction/x:TransNo"/>
      <xsl:copy-of select="x:Transaction/x:RegisterNo"/>
      <xsl:copy-of select="x:Transaction/x:Items"/>
 </xsl:copy>      
</xsl:template>

Ответы [ 3 ]

2 голосов
/ 04 октября 2011

Это преобразование использует список всех имен элементов, которые мы хотим скопировать после обработки :

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 xmlns:x="http://invia.fujitsu.com/RetailDATACenter/rdc.xsd">
    <xsl:output omit-xml-declaration="yes" indent="yes"/>
    <xsl:strip-space elements="*"/>

    <xsl:param name="pNames" select=
    "'|Transaction|StoreName|TransNo|RegisterNo|Items|Item|ItemID|ItemDesc'"/>

    <xsl:template match="*" >
     <xsl:if test=
      "contains($pNames,
                concat('|',local-name(), '|')
              )">
        <xsl:element name="{name()}">
            <xsl:copy-of select="@*"/>
            <xsl:apply-templates select="node()"/>
        </xsl:element>
     </xsl:if>
    </xsl:template>

    <xsl:template match="node()[not(self::*)]">
        <xsl:copy-of select="."/>
    </xsl:template>
</xsl:stylesheet>

применительно к предоставленному XML-документу :

<Transaction xmlns="http://www.test.com/rdc.xsd">
    <Transaction>
        <StoreName id="aa">STORE A</StoreName>
        <TransNo>TXN0001</TransNo>
        <RegisterNo>REG001</RegisterNo>
        <Items>
            <Item id="1">
                <ItemID>A001</ItemID>
                <ItemDesc>Keychain</ItemDesc>
            </Item>
            <Item id="2">
                <ItemID>A002</ItemID>
                <ItemDesc>Wallet</ItemDesc>
            </Item>
        </Items>
        <IDONTLIKETHIS_1>
            <STOREXXX>XXX</STOREXXX>
            <TRANSXXX>YYY</TRANSXXX>
        </IDONTLIKETHIS_1>
        <IDONTLIKETHIS_2>
            <STOREXXX>XXX</STOREXXX>
            <TRANSXXX>YYY</TRANSXXX>
        </IDONTLIKETHIS_2>
    </Transaction>
</Transaction>

желаемый, правильный результат:

<Transaction>
   <Transaction>
      <StoreName id="aa">STORE A</StoreName>
      <TransNo>TXN0001</TransNo>
      <RegisterNo>REG001</RegisterNo>
      <Items>
         <Item id="1">
            <ItemID>A001</ItemID>
         </Item>
         <Item id="2">
            <ItemID>A002</ItemID>
         </Item>
      </Items>
   </Transaction>
</Transaction>

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

1 голос
/ 03 октября 2011

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

Надеюсь, это поможет,

Ken

<xsl:stylesheet version="1.0" xmlns:abc="http://www.test.com/rdc.xsd" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 

<xsl:template match="abc:Transaction|abc:StoreName|abc:TransNo|abc:RegisterNo|abc:Items|abc:Item|abc:ItemID|abc:ItemDesc">
    <xsl:element name="{local-name()}"> 
        <xsl:copy-of select="@*"/>
        <xsl:apply-templates/>
    </xsl:element>
</xsl:template>

<xsl:template match="@*"> 
    <xsl:copy/> 
</xsl:template> 

<xsl:template match="*"/>


</xsl:stylesheet> 
1 голос
/ 03 октября 2011

Будет ли это работать?

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="2.0">
  <xsl:variable name="allowed">
    <names>
      <name>Transaction</name>
      <name>StoreName</name>
      <name>TransNo</name>
      <name>RegisterNo</name>
      <name>Items</name>
      <name>Item</name>
      <name>ItemID</name>
      <name>ItemDesc</name>
      <name>id</name>
    </names>
  </xsl:variable>
  <xsl:template match="text()">
    <xsl:copy-of select="."/>
  </xsl:template>
  <xsl:template match="@*">
    <xsl:copy-of select="."/>
  </xsl:template>
  <xsl:template match="comment()">
    <xsl:copy-of select="."/>
  </xsl:template>
  <xsl:template match="processing-instruction()">
    <xsl:copy-of select="."/>
  </xsl:template>
  <xsl:template match="*">
    <xsl:if test="local-name(.) = $allowed//name">
      <xsl:element name="{local-name(.)}">
        <xsl:apply-templates select="@*"/>
        <xsl:apply-templates select="node()"/>
      </xsl:element>
    </xsl:if>
  </xsl:template>
</xsl:stylesheet>
...